@ng-forge/dynamic-forms-ionic 0.1.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.
|
@@ -0,0 +1,2045 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, input, computed, ChangeDetectionStrategy, Component, signal, InjectionToken, Pipe, linkedSignal, model, isSignal } from '@angular/core';
|
|
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, createResolvedErrorsSignal, shouldShowErrors, buildBaseInputs, FIELD_SIGNAL_CONTEXT, resolveSubmitButtonDisabled, resolveNextButtonDisabled, NextPageEvent, PreviousPageEvent, AddArrayItemEvent, RemoveArrayItemEvent, valueFieldMapper, optionsFieldMapper, checkboxFieldMapper, datepickerFieldMapper } from '@ng-forge/dynamic-forms';
|
|
5
|
+
import { AsyncPipe } from '@angular/common';
|
|
6
|
+
import { Field } from '@angular/forms/signals';
|
|
7
|
+
import { format } from 'date-fns';
|
|
8
|
+
import { explicitEffect } from 'ngxtension/explicit-effect';
|
|
9
|
+
|
|
10
|
+
class IonicButtonFieldComponent {
|
|
11
|
+
eventBus = inject(EventBus);
|
|
12
|
+
arrayContext = inject(ARRAY_CONTEXT, { optional: true });
|
|
13
|
+
key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}) });
|
|
14
|
+
label = input.required({ ...(ngDevMode ? { debugName: "label" } : {}) });
|
|
15
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : {}) });
|
|
16
|
+
hidden = input(false, { ...(ngDevMode ? { debugName: "hidden" } : {}) });
|
|
17
|
+
tabIndex = input(undefined, { ...(ngDevMode ? { debugName: "tabIndex" } : {}) });
|
|
18
|
+
className = input('', { ...(ngDevMode ? { debugName: "className" } : {}) });
|
|
19
|
+
/** Event to dispatch on click. Optional for submit buttons (native form submit handles it). */
|
|
20
|
+
event = input(undefined, { ...(ngDevMode ? { debugName: "event" } : {}) });
|
|
21
|
+
eventArgs = input(undefined, { ...(ngDevMode ? { debugName: "eventArgs" } : {}) });
|
|
22
|
+
props = input(undefined, { ...(ngDevMode ? { debugName: "props" } : {}) });
|
|
23
|
+
eventContext = input(undefined, { ...(ngDevMode ? { debugName: "eventContext" } : {}) });
|
|
24
|
+
/** Resolved button type - defaults to 'button' if not specified in props */
|
|
25
|
+
buttonType = computed(() => this.props()?.type ?? 'button', { ...(ngDevMode ? { debugName: "buttonType" } : {}) });
|
|
26
|
+
buttonTestId = computed(() => `${this.buttonType()}-${this.key()}`, { ...(ngDevMode ? { debugName: "buttonTestId" } : {}) });
|
|
27
|
+
/**
|
|
28
|
+
* Handle button click.
|
|
29
|
+
* - For submit buttons (type="submit"): do nothing, native form submit handles it
|
|
30
|
+
* - For other buttons: dispatch the configured event via EventBus
|
|
31
|
+
*/
|
|
32
|
+
onClick() {
|
|
33
|
+
// Native submit buttons let the form handle submission
|
|
34
|
+
if (this.buttonType() === 'submit') {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// Other buttons dispatch their event (if configured)
|
|
38
|
+
const event = this.event();
|
|
39
|
+
if (event) {
|
|
40
|
+
this.dispatchEvent(event);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
dispatchEvent(event) {
|
|
44
|
+
const args = this.eventArgs();
|
|
45
|
+
if (args && args.length > 0) {
|
|
46
|
+
// Build context from injected ARRAY_CONTEXT (with linkedSignal index) or fallback to eventContext
|
|
47
|
+
const context = this.arrayContext
|
|
48
|
+
? {
|
|
49
|
+
key: this.key(),
|
|
50
|
+
// Read signal to get current index (automatically updates via linkedSignal)
|
|
51
|
+
index: this.arrayContext.index(),
|
|
52
|
+
arrayKey: this.arrayContext.arrayKey,
|
|
53
|
+
formValue: this.arrayContext.formValue,
|
|
54
|
+
}
|
|
55
|
+
: this.eventContext() || { key: this.key() };
|
|
56
|
+
// Resolve tokens in event args using the provided context
|
|
57
|
+
const resolvedArgs = resolveTokens(args, context);
|
|
58
|
+
// Dispatch event with resolved args
|
|
59
|
+
this.eventBus.dispatch(event, ...resolvedArgs);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// No args, dispatch event without arguments
|
|
63
|
+
this.eventBus.dispatch(event);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicButtonFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
67
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.1", type: IonicButtonFieldComponent, isStandalone: true, selector: "df-ionic-button", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, event: { classPropertyName: "event", publicName: "event", isSignal: true, isRequired: false, transformFunction: null }, eventArgs: { classPropertyName: "eventArgs", publicName: "eventArgs", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, eventContext: { classPropertyName: "eventContext", publicName: "eventContext", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()" } }, ngImport: i0, template: `
|
|
68
|
+
<ion-button
|
|
69
|
+
[type]="buttonType()"
|
|
70
|
+
[expand]="props()?.expand"
|
|
71
|
+
[fill]="props()?.fill || 'solid'"
|
|
72
|
+
[shape]="props()?.shape"
|
|
73
|
+
[size]="props()?.size"
|
|
74
|
+
[color]="props()?.color || 'primary'"
|
|
75
|
+
[strong]="props()?.strong"
|
|
76
|
+
[class]="className() || ''"
|
|
77
|
+
[disabled]="disabled()"
|
|
78
|
+
[attr.data-testid]="buttonTestId()"
|
|
79
|
+
(click)="onClick()"
|
|
80
|
+
>
|
|
81
|
+
{{ label() | dynamicText | async }}
|
|
82
|
+
</ion-button>
|
|
83
|
+
`, isInline: true, 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 });
|
|
84
|
+
}
|
|
85
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicButtonFieldComponent, decorators: [{
|
|
86
|
+
type: Component,
|
|
87
|
+
args: [{
|
|
88
|
+
selector: 'df-ionic-button',
|
|
89
|
+
imports: [IonButton, DynamicTextPipe, AsyncPipe],
|
|
90
|
+
host: {
|
|
91
|
+
'[id]': '`${key()}`',
|
|
92
|
+
'[attr.data-testid]': 'key()',
|
|
93
|
+
},
|
|
94
|
+
template: `
|
|
95
|
+
<ion-button
|
|
96
|
+
[type]="buttonType()"
|
|
97
|
+
[expand]="props()?.expand"
|
|
98
|
+
[fill]="props()?.fill || 'solid'"
|
|
99
|
+
[shape]="props()?.shape"
|
|
100
|
+
[size]="props()?.size"
|
|
101
|
+
[color]="props()?.color || 'primary'"
|
|
102
|
+
[strong]="props()?.strong"
|
|
103
|
+
[class]="className() || ''"
|
|
104
|
+
[disabled]="disabled()"
|
|
105
|
+
[attr.data-testid]="buttonTestId()"
|
|
106
|
+
(click)="onClick()"
|
|
107
|
+
>
|
|
108
|
+
{{ label() | dynamicText | async }}
|
|
109
|
+
</ion-button>
|
|
110
|
+
`,
|
|
111
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
112
|
+
}]
|
|
113
|
+
}], propDecorators: { key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], event: [{ type: i0.Input, args: [{ isSignal: true, alias: "event", required: false }] }], eventArgs: [{ type: i0.Input, args: [{ isSignal: true, alias: "eventArgs", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], eventContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "eventContext", required: false }] }] } });
|
|
114
|
+
|
|
115
|
+
var ionicButton_component = /*#__PURE__*/Object.freeze({
|
|
116
|
+
__proto__: null,
|
|
117
|
+
default: IonicButtonFieldComponent
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Public API - component
|
|
121
|
+
|
|
122
|
+
class IonicCheckboxFieldComponent {
|
|
123
|
+
field = input.required({ ...(ngDevMode ? { debugName: "field" } : {}) });
|
|
124
|
+
key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}) });
|
|
125
|
+
// Properties
|
|
126
|
+
label = input(undefined, { ...(ngDevMode ? { debugName: "label" } : {}) });
|
|
127
|
+
placeholder = input(undefined, { ...(ngDevMode ? { debugName: "placeholder" } : {}) });
|
|
128
|
+
className = input('', { ...(ngDevMode ? { debugName: "className" } : {}) });
|
|
129
|
+
tabIndex = input(undefined, { ...(ngDevMode ? { debugName: "tabIndex" } : {}) });
|
|
130
|
+
props = input(undefined, { ...(ngDevMode ? { debugName: "props" } : {}) });
|
|
131
|
+
validationMessages = input(undefined, { ...(ngDevMode ? { debugName: "validationMessages" } : {}) });
|
|
132
|
+
defaultValidationMessages = input(undefined, { ...(ngDevMode ? { debugName: "defaultValidationMessages" } : {}) });
|
|
133
|
+
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
134
|
+
showErrors = shouldShowErrors(this.field);
|
|
135
|
+
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), { ...(ngDevMode ? { debugName: "errorsToDisplay" } : {}) });
|
|
136
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
137
|
+
// Accessibility
|
|
138
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
139
|
+
/** Base ID for error elements */
|
|
140
|
+
errorId = computed(() => `${this.key()}-error`, { ...(ngDevMode ? { debugName: "errorId" } : {}) });
|
|
141
|
+
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
142
|
+
isAriaInvalid = computed(() => {
|
|
143
|
+
const fieldState = this.field()();
|
|
144
|
+
return fieldState.invalid() && fieldState.touched();
|
|
145
|
+
}, { ...(ngDevMode ? { debugName: "isAriaInvalid" } : {}) });
|
|
146
|
+
/** Whether the field has a required validator */
|
|
147
|
+
isRequired = computed(() => {
|
|
148
|
+
return this.field()().required?.() === true;
|
|
149
|
+
}, { ...(ngDevMode ? { debugName: "isRequired" } : {}) });
|
|
150
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
151
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: IonicCheckboxFieldComponent, isStandalone: true, selector: "df-ionic-checkbox", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
|
|
152
|
+
@let f = field();
|
|
153
|
+
|
|
154
|
+
<ion-checkbox
|
|
155
|
+
[field]="f"
|
|
156
|
+
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
157
|
+
[justify]="props()?.justify"
|
|
158
|
+
[color]="props()?.color ?? 'primary'"
|
|
159
|
+
[indeterminate]="props()?.indeterminate ?? false"
|
|
160
|
+
[attr.tabindex]="tabIndex()"
|
|
161
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
162
|
+
[attr.aria-required]="isRequired() || null"
|
|
163
|
+
>
|
|
164
|
+
{{ label() | dynamicText | async }}
|
|
165
|
+
</ion-checkbox>
|
|
166
|
+
|
|
167
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
168
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
169
|
+
}
|
|
170
|
+
`, isInline: true, styles: [":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: Field, selector: "[field]", inputs: ["field"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
171
|
+
}
|
|
172
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicCheckboxFieldComponent, decorators: [{
|
|
173
|
+
type: Component,
|
|
174
|
+
args: [{ selector: 'df-ionic-checkbox', imports: [IonCheckbox, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
|
|
175
|
+
@let f = field();
|
|
176
|
+
|
|
177
|
+
<ion-checkbox
|
|
178
|
+
[field]="f"
|
|
179
|
+
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
180
|
+
[justify]="props()?.justify"
|
|
181
|
+
[color]="props()?.color ?? 'primary'"
|
|
182
|
+
[indeterminate]="props()?.indeterminate ?? false"
|
|
183
|
+
[attr.tabindex]="tabIndex()"
|
|
184
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
185
|
+
[attr.aria-required]="isRequired() || null"
|
|
186
|
+
>
|
|
187
|
+
{{ label() | dynamicText | async }}
|
|
188
|
+
</ion-checkbox>
|
|
189
|
+
|
|
190
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
191
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
192
|
+
}
|
|
193
|
+
`, host: {
|
|
194
|
+
'[class]': 'className()',
|
|
195
|
+
'[id]': '`${key()}`',
|
|
196
|
+
'[attr.data-testid]': 'key()',
|
|
197
|
+
'[attr.hidden]': 'field()().hidden() || null',
|
|
198
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}:host([hidden]){display:none!important}\n"] }]
|
|
199
|
+
}], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
200
|
+
|
|
201
|
+
var ionicCheckbox_component = /*#__PURE__*/Object.freeze({
|
|
202
|
+
__proto__: null,
|
|
203
|
+
default: IonicCheckboxFieldComponent
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
class IonicDatepickerFieldComponent {
|
|
207
|
+
field = input.required({ ...(ngDevMode ? { debugName: "field" } : {}) });
|
|
208
|
+
key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}) });
|
|
209
|
+
label = input(undefined, { ...(ngDevMode ? { debugName: "label" } : {}) });
|
|
210
|
+
placeholder = input(undefined, { ...(ngDevMode ? { debugName: "placeholder" } : {}) });
|
|
211
|
+
className = input('', { ...(ngDevMode ? { debugName: "className" } : {}) });
|
|
212
|
+
tabIndex = input(undefined, { ...(ngDevMode ? { debugName: "tabIndex" } : {}) });
|
|
213
|
+
minDate = input(null, { ...(ngDevMode ? { debugName: "minDate" } : {}) });
|
|
214
|
+
maxDate = input(null, { ...(ngDevMode ? { debugName: "maxDate" } : {}) });
|
|
215
|
+
startAt = input(null, { ...(ngDevMode ? { debugName: "startAt" } : {}) });
|
|
216
|
+
props = input(undefined, { ...(ngDevMode ? { debugName: "props" } : {}) });
|
|
217
|
+
validationMessages = input(undefined, { ...(ngDevMode ? { debugName: "validationMessages" } : {}) });
|
|
218
|
+
defaultValidationMessages = input(undefined, { ...(ngDevMode ? { debugName: "defaultValidationMessages" } : {}) });
|
|
219
|
+
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
220
|
+
showErrors = shouldShowErrors(this.field);
|
|
221
|
+
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), { ...(ngDevMode ? { debugName: "errorsToDisplay" } : {}) });
|
|
222
|
+
isModalOpen = signal(false, { ...(ngDevMode ? { debugName: "isModalOpen" } : {}) });
|
|
223
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
224
|
+
// Accessibility
|
|
225
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
226
|
+
/** Base ID for error elements */
|
|
227
|
+
errorId = computed(() => `${this.key()}-error`, { ...(ngDevMode ? { debugName: "errorId" } : {}) });
|
|
228
|
+
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
229
|
+
isAriaInvalid = computed(() => {
|
|
230
|
+
const fieldState = this.field()();
|
|
231
|
+
return fieldState.invalid() && fieldState.touched();
|
|
232
|
+
}, { ...(ngDevMode ? { debugName: "isAriaInvalid" } : {}) });
|
|
233
|
+
/** Whether the field has a required validator */
|
|
234
|
+
isRequired = computed(() => {
|
|
235
|
+
return this.field()().required?.() === true;
|
|
236
|
+
}, { ...(ngDevMode ? { debugName: "isRequired" } : {}) });
|
|
237
|
+
openModal() {
|
|
238
|
+
this.isModalOpen.set(true);
|
|
239
|
+
}
|
|
240
|
+
closeModal() {
|
|
241
|
+
this.isModalOpen.set(false);
|
|
242
|
+
}
|
|
243
|
+
onDateChange(event) {
|
|
244
|
+
const value = event.detail.value;
|
|
245
|
+
if (value) {
|
|
246
|
+
const date = new Date(value);
|
|
247
|
+
this.field()().value.set(date);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
this.field()().value.set(null);
|
|
251
|
+
}
|
|
252
|
+
this.closeModal();
|
|
253
|
+
}
|
|
254
|
+
dateToIsoString(date) {
|
|
255
|
+
if (!date)
|
|
256
|
+
return undefined;
|
|
257
|
+
return date.toISOString();
|
|
258
|
+
}
|
|
259
|
+
formatDisplayDate(date) {
|
|
260
|
+
if (!date)
|
|
261
|
+
return '';
|
|
262
|
+
const presentation = this.props()?.presentation ?? 'date';
|
|
263
|
+
switch (presentation) {
|
|
264
|
+
case 'date':
|
|
265
|
+
return format(date, 'MMM d, yyyy');
|
|
266
|
+
case 'date-time':
|
|
267
|
+
case 'time-date':
|
|
268
|
+
return format(date, 'MMM d, yyyy, h:mm a');
|
|
269
|
+
case 'time':
|
|
270
|
+
return format(date, 'h:mm a');
|
|
271
|
+
case 'month':
|
|
272
|
+
return format(date, 'MMMM yyyy');
|
|
273
|
+
case 'month-year':
|
|
274
|
+
return format(date, 'MMM yyyy');
|
|
275
|
+
case 'year':
|
|
276
|
+
return format(date, 'yyyy');
|
|
277
|
+
default:
|
|
278
|
+
return format(date, 'MMM d, yyyy');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicDatepickerFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
282
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: IonicDatepickerFieldComponent, isStandalone: true, selector: "df-ionic-datepicker", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
|
|
283
|
+
@let f = field(); @let dateValue = f().value();
|
|
284
|
+
|
|
285
|
+
<ion-input
|
|
286
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
287
|
+
[labelPlacement]="'stacked'"
|
|
288
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
289
|
+
[disabled]="f().disabled()"
|
|
290
|
+
[value]="formatDisplayDate(dateValue)"
|
|
291
|
+
[readonly]="true"
|
|
292
|
+
[fill]="'outline'"
|
|
293
|
+
[attr.tabindex]="tabIndex()"
|
|
294
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
295
|
+
[attr.aria-required]="isRequired() || null"
|
|
296
|
+
[class.ion-invalid]="f().invalid()"
|
|
297
|
+
[class.ion-touched]="f().touched()"
|
|
298
|
+
(click)="!f().disabled() && openModal()"
|
|
299
|
+
>
|
|
300
|
+
<div slot="error">
|
|
301
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
302
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
303
|
+
}
|
|
304
|
+
</div>
|
|
305
|
+
</ion-input>
|
|
306
|
+
|
|
307
|
+
<ion-modal [isOpen]="isModalOpen()" (didDismiss)="closeModal()">
|
|
308
|
+
<ng-template>
|
|
309
|
+
<ion-header>
|
|
310
|
+
<ion-toolbar>
|
|
311
|
+
<ion-title>{{ label() | dynamicText | async }}</ion-title>
|
|
312
|
+
<ion-buttons slot="end">
|
|
313
|
+
<ion-button (click)="closeModal()">Close</ion-button>
|
|
314
|
+
</ion-buttons>
|
|
315
|
+
</ion-toolbar>
|
|
316
|
+
</ion-header>
|
|
317
|
+
<ion-content>
|
|
318
|
+
<ion-datetime
|
|
319
|
+
[presentation]="props()?.presentation ?? 'date'"
|
|
320
|
+
[value]="dateToIsoString(dateValue)"
|
|
321
|
+
[multiple]="props()?.multiple ?? false"
|
|
322
|
+
[preferWheel]="props()?.preferWheel ?? false"
|
|
323
|
+
[showDefaultButtons]="props()?.showDefaultButtons ?? false"
|
|
324
|
+
[showDefaultTitle]="props()?.showDefaultTitle ?? false"
|
|
325
|
+
[showDefaultTimeLabel]="props()?.showDefaultTimeLabel ?? true"
|
|
326
|
+
[showClearButton]="props()?.showClearButton ?? false"
|
|
327
|
+
[color]="props()?.color"
|
|
328
|
+
[min]="dateToIsoString(minDate())"
|
|
329
|
+
[max]="dateToIsoString(maxDate())"
|
|
330
|
+
(ionChange)="onDateChange($event)"
|
|
331
|
+
>
|
|
332
|
+
</ion-datetime>
|
|
333
|
+
</ion-content>
|
|
334
|
+
</ng-template>
|
|
335
|
+
</ion-modal>
|
|
336
|
+
`, isInline: true, styles: ["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: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
337
|
+
}
|
|
338
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicDatepickerFieldComponent, decorators: [{
|
|
339
|
+
type: Component,
|
|
340
|
+
args: [{ selector: 'df-ionic-datepicker', imports: [
|
|
341
|
+
IonInput,
|
|
342
|
+
IonModal,
|
|
343
|
+
IonDatetime,
|
|
344
|
+
IonNote,
|
|
345
|
+
IonButtons,
|
|
346
|
+
IonHeader,
|
|
347
|
+
IonContent,
|
|
348
|
+
IonToolbar,
|
|
349
|
+
IonTitle,
|
|
350
|
+
IonButton,
|
|
351
|
+
DynamicTextPipe,
|
|
352
|
+
AsyncPipe,
|
|
353
|
+
], template: `
|
|
354
|
+
@let f = field(); @let dateValue = f().value();
|
|
355
|
+
|
|
356
|
+
<ion-input
|
|
357
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
358
|
+
[labelPlacement]="'stacked'"
|
|
359
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
360
|
+
[disabled]="f().disabled()"
|
|
361
|
+
[value]="formatDisplayDate(dateValue)"
|
|
362
|
+
[readonly]="true"
|
|
363
|
+
[fill]="'outline'"
|
|
364
|
+
[attr.tabindex]="tabIndex()"
|
|
365
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
366
|
+
[attr.aria-required]="isRequired() || null"
|
|
367
|
+
[class.ion-invalid]="f().invalid()"
|
|
368
|
+
[class.ion-touched]="f().touched()"
|
|
369
|
+
(click)="!f().disabled() && openModal()"
|
|
370
|
+
>
|
|
371
|
+
<div slot="error">
|
|
372
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
373
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
374
|
+
}
|
|
375
|
+
</div>
|
|
376
|
+
</ion-input>
|
|
377
|
+
|
|
378
|
+
<ion-modal [isOpen]="isModalOpen()" (didDismiss)="closeModal()">
|
|
379
|
+
<ng-template>
|
|
380
|
+
<ion-header>
|
|
381
|
+
<ion-toolbar>
|
|
382
|
+
<ion-title>{{ label() | dynamicText | async }}</ion-title>
|
|
383
|
+
<ion-buttons slot="end">
|
|
384
|
+
<ion-button (click)="closeModal()">Close</ion-button>
|
|
385
|
+
</ion-buttons>
|
|
386
|
+
</ion-toolbar>
|
|
387
|
+
</ion-header>
|
|
388
|
+
<ion-content>
|
|
389
|
+
<ion-datetime
|
|
390
|
+
[presentation]="props()?.presentation ?? 'date'"
|
|
391
|
+
[value]="dateToIsoString(dateValue)"
|
|
392
|
+
[multiple]="props()?.multiple ?? false"
|
|
393
|
+
[preferWheel]="props()?.preferWheel ?? false"
|
|
394
|
+
[showDefaultButtons]="props()?.showDefaultButtons ?? false"
|
|
395
|
+
[showDefaultTitle]="props()?.showDefaultTitle ?? false"
|
|
396
|
+
[showDefaultTimeLabel]="props()?.showDefaultTimeLabel ?? true"
|
|
397
|
+
[showClearButton]="props()?.showClearButton ?? false"
|
|
398
|
+
[color]="props()?.color"
|
|
399
|
+
[min]="dateToIsoString(minDate())"
|
|
400
|
+
[max]="dateToIsoString(maxDate())"
|
|
401
|
+
(ionChange)="onDateChange($event)"
|
|
402
|
+
>
|
|
403
|
+
</ion-datetime>
|
|
404
|
+
</ion-content>
|
|
405
|
+
</ng-template>
|
|
406
|
+
</ion-modal>
|
|
407
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
408
|
+
'[id]': '`${key()}`',
|
|
409
|
+
'[attr.data-testid]': 'key()',
|
|
410
|
+
'[class]': 'className()',
|
|
411
|
+
'[attr.hidden]': 'field()().hidden() || null',
|
|
412
|
+
}, styles: ["ion-input{cursor:pointer}:host([hidden]){display:none!important}\n"] }]
|
|
413
|
+
}], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], startAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAt", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
414
|
+
|
|
415
|
+
var ionicDatepicker_component = /*#__PURE__*/Object.freeze({
|
|
416
|
+
__proto__: null,
|
|
417
|
+
default: IonicDatepickerFieldComponent
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Injection token for Ionic form configuration.
|
|
422
|
+
* Use this to provide global configuration for Ionic form fields.
|
|
423
|
+
*
|
|
424
|
+
* @example
|
|
425
|
+
* ```typescript
|
|
426
|
+
* import { provideDynamicForm } from '@ng-forge/dynamic-forms';
|
|
427
|
+
* import { withIonicFields } from '@ng-forge/dynamic-forms-ionic';
|
|
428
|
+
*
|
|
429
|
+
* export const appConfig: ApplicationConfig = {
|
|
430
|
+
* providers: [
|
|
431
|
+
* provideDynamicForm(
|
|
432
|
+
* ...withIonicFields({
|
|
433
|
+
* fill: 'outline',
|
|
434
|
+
* labelPlacement: 'floating'
|
|
435
|
+
* })
|
|
436
|
+
* )
|
|
437
|
+
* ]
|
|
438
|
+
* };
|
|
439
|
+
* ```
|
|
440
|
+
*/
|
|
441
|
+
const IONIC_CONFIG = new InjectionToken('IONIC_CONFIG');
|
|
442
|
+
|
|
443
|
+
class IonicInputFieldComponent {
|
|
444
|
+
ionicConfig = inject(IONIC_CONFIG, { optional: true });
|
|
445
|
+
field = input.required({ ...(ngDevMode ? { debugName: "field" } : {}) });
|
|
446
|
+
key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}) });
|
|
447
|
+
label = input(undefined, { ...(ngDevMode ? { debugName: "label" } : {}) });
|
|
448
|
+
placeholder = input(undefined, { ...(ngDevMode ? { debugName: "placeholder" } : {}) });
|
|
449
|
+
className = input('', { ...(ngDevMode ? { debugName: "className" } : {}) });
|
|
450
|
+
tabIndex = input(undefined, { ...(ngDevMode ? { debugName: "tabIndex" } : {}) });
|
|
451
|
+
props = input(undefined, { ...(ngDevMode ? { debugName: "props" } : {}) });
|
|
452
|
+
validationMessages = input(undefined, { ...(ngDevMode ? { debugName: "validationMessages" } : {}) });
|
|
453
|
+
defaultValidationMessages = input(undefined, { ...(ngDevMode ? { debugName: "defaultValidationMessages" } : {}) });
|
|
454
|
+
effectiveFill = computed(() => this.props()?.fill ?? this.ionicConfig?.fill ?? 'solid', { ...(ngDevMode ? { debugName: "effectiveFill" } : {}) });
|
|
455
|
+
effectiveShape = computed(() => this.props()?.shape ?? this.ionicConfig?.shape, { ...(ngDevMode ? { debugName: "effectiveShape" } : {}) });
|
|
456
|
+
effectiveLabelPlacement = computed(() => this.props()?.labelPlacement ?? this.ionicConfig?.labelPlacement ?? 'start', { ...(ngDevMode ? { debugName: "effectiveLabelPlacement" } : {}) });
|
|
457
|
+
effectiveColor = computed(() => this.props()?.color ?? this.ionicConfig?.color, { ...(ngDevMode ? { debugName: "effectiveColor" } : {}) });
|
|
458
|
+
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
459
|
+
showErrors = shouldShowErrors(this.field);
|
|
460
|
+
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), { ...(ngDevMode ? { debugName: "errorsToDisplay" } : {}) });
|
|
461
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
462
|
+
// Accessibility
|
|
463
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
464
|
+
/** Base ID for error elements */
|
|
465
|
+
errorId = computed(() => `${this.key()}-error`, { ...(ngDevMode ? { debugName: "errorId" } : {}) });
|
|
466
|
+
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
467
|
+
isAriaInvalid = computed(() => {
|
|
468
|
+
const fieldState = this.field()();
|
|
469
|
+
return fieldState.invalid() && fieldState.touched();
|
|
470
|
+
}, { ...(ngDevMode ? { debugName: "isAriaInvalid" } : {}) });
|
|
471
|
+
/** Whether the field has a required validator */
|
|
472
|
+
isRequired = computed(() => {
|
|
473
|
+
return this.field()().required?.() === true;
|
|
474
|
+
}, { ...(ngDevMode ? { debugName: "isRequired" } : {}) });
|
|
475
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicInputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
476
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: IonicInputFieldComponent, isStandalone: true, selector: "df-ionic-input", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
|
|
477
|
+
@let f = field();
|
|
478
|
+
@let ariaInvalid = isAriaInvalid();
|
|
479
|
+
@let ariaRequired = isRequired() || null;
|
|
480
|
+
|
|
481
|
+
@switch (props()?.type ?? 'text') {
|
|
482
|
+
@case ('email') {
|
|
483
|
+
<ion-input
|
|
484
|
+
type="email"
|
|
485
|
+
[field]="f"
|
|
486
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
487
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
488
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
489
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
490
|
+
[counter]="props()?.counter ?? false"
|
|
491
|
+
[color]="effectiveColor()"
|
|
492
|
+
[fill]="effectiveFill()"
|
|
493
|
+
[shape]="effectiveShape()"
|
|
494
|
+
[readonly]="f().readonly()"
|
|
495
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
496
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
497
|
+
[attr.tabindex]="tabIndex()"
|
|
498
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
499
|
+
[attr.aria-required]="ariaRequired"
|
|
500
|
+
[class.ion-invalid]="f().invalid()"
|
|
501
|
+
[class.ion-touched]="f().touched()"
|
|
502
|
+
>
|
|
503
|
+
<div slot="error">
|
|
504
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
505
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
506
|
+
}
|
|
507
|
+
</div>
|
|
508
|
+
</ion-input>
|
|
509
|
+
}
|
|
510
|
+
@case ('password') {
|
|
511
|
+
<ion-input
|
|
512
|
+
type="password"
|
|
513
|
+
[field]="f"
|
|
514
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
515
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
516
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
517
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
518
|
+
[counter]="props()?.counter ?? false"
|
|
519
|
+
[color]="effectiveColor()"
|
|
520
|
+
[fill]="effectiveFill()"
|
|
521
|
+
[shape]="effectiveShape()"
|
|
522
|
+
[readonly]="f().readonly()"
|
|
523
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
524
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
525
|
+
[attr.tabindex]="tabIndex()"
|
|
526
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
527
|
+
[attr.aria-required]="ariaRequired"
|
|
528
|
+
[class.ion-invalid]="f().invalid()"
|
|
529
|
+
[class.ion-touched]="f().touched()"
|
|
530
|
+
>
|
|
531
|
+
<div slot="error">
|
|
532
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
533
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
534
|
+
}
|
|
535
|
+
</div>
|
|
536
|
+
</ion-input>
|
|
537
|
+
}
|
|
538
|
+
@case ('number') {
|
|
539
|
+
<ion-input
|
|
540
|
+
type="number"
|
|
541
|
+
[field]="f"
|
|
542
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
543
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
544
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
545
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
546
|
+
[counter]="props()?.counter ?? false"
|
|
547
|
+
[color]="effectiveColor()"
|
|
548
|
+
[fill]="effectiveFill()"
|
|
549
|
+
[shape]="effectiveShape()"
|
|
550
|
+
[readonly]="f().readonly()"
|
|
551
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
552
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
553
|
+
[attr.tabindex]="tabIndex()"
|
|
554
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
555
|
+
[attr.aria-required]="ariaRequired"
|
|
556
|
+
[class.ion-invalid]="f().invalid()"
|
|
557
|
+
[class.ion-touched]="f().touched()"
|
|
558
|
+
>
|
|
559
|
+
<div slot="error">
|
|
560
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
561
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
562
|
+
}
|
|
563
|
+
</div>
|
|
564
|
+
</ion-input>
|
|
565
|
+
}
|
|
566
|
+
@case ('tel') {
|
|
567
|
+
<ion-input
|
|
568
|
+
type="tel"
|
|
569
|
+
[field]="f"
|
|
570
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
571
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
572
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
573
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
574
|
+
[counter]="props()?.counter ?? false"
|
|
575
|
+
[color]="effectiveColor()"
|
|
576
|
+
[fill]="effectiveFill()"
|
|
577
|
+
[shape]="effectiveShape()"
|
|
578
|
+
[readonly]="f().readonly()"
|
|
579
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
580
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
581
|
+
[attr.tabindex]="tabIndex()"
|
|
582
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
583
|
+
[attr.aria-required]="ariaRequired"
|
|
584
|
+
[class.ion-invalid]="f().invalid()"
|
|
585
|
+
[class.ion-touched]="f().touched()"
|
|
586
|
+
>
|
|
587
|
+
<div slot="error">
|
|
588
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
589
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
590
|
+
}
|
|
591
|
+
</div>
|
|
592
|
+
</ion-input>
|
|
593
|
+
}
|
|
594
|
+
@case ('url') {
|
|
595
|
+
<ion-input
|
|
596
|
+
type="url"
|
|
597
|
+
[field]="f"
|
|
598
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
599
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
600
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
601
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
602
|
+
[counter]="props()?.counter ?? false"
|
|
603
|
+
[color]="effectiveColor()"
|
|
604
|
+
[fill]="effectiveFill()"
|
|
605
|
+
[shape]="effectiveShape()"
|
|
606
|
+
[readonly]="f().readonly()"
|
|
607
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
608
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
609
|
+
[attr.tabindex]="tabIndex()"
|
|
610
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
611
|
+
[attr.aria-required]="ariaRequired"
|
|
612
|
+
[class.ion-invalid]="f().invalid()"
|
|
613
|
+
[class.ion-touched]="f().touched()"
|
|
614
|
+
>
|
|
615
|
+
<div slot="error">
|
|
616
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
617
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
618
|
+
}
|
|
619
|
+
</div>
|
|
620
|
+
</ion-input>
|
|
621
|
+
}
|
|
622
|
+
@default {
|
|
623
|
+
<ion-input
|
|
624
|
+
type="text"
|
|
625
|
+
[field]="f"
|
|
626
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
627
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
628
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
629
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
630
|
+
[counter]="props()?.counter ?? false"
|
|
631
|
+
[color]="effectiveColor()"
|
|
632
|
+
[fill]="effectiveFill()"
|
|
633
|
+
[shape]="effectiveShape()"
|
|
634
|
+
[readonly]="f().readonly()"
|
|
635
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
636
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
637
|
+
[attr.tabindex]="tabIndex()"
|
|
638
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
639
|
+
[attr.aria-required]="ariaRequired"
|
|
640
|
+
[class.ion-invalid]="f().invalid()"
|
|
641
|
+
[class.ion-touched]="f().touched()"
|
|
642
|
+
>
|
|
643
|
+
<div slot="error">
|
|
644
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
645
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
646
|
+
}
|
|
647
|
+
</div>
|
|
648
|
+
</ion-input>
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
`, isInline: true, styles: [":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: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: Field, selector: "[field]", inputs: ["field"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
652
|
+
}
|
|
653
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicInputFieldComponent, decorators: [{
|
|
654
|
+
type: Component,
|
|
655
|
+
args: [{ selector: 'df-ionic-input', imports: [IonInput, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
|
|
656
|
+
@let f = field();
|
|
657
|
+
@let ariaInvalid = isAriaInvalid();
|
|
658
|
+
@let ariaRequired = isRequired() || null;
|
|
659
|
+
|
|
660
|
+
@switch (props()?.type ?? 'text') {
|
|
661
|
+
@case ('email') {
|
|
662
|
+
<ion-input
|
|
663
|
+
type="email"
|
|
664
|
+
[field]="f"
|
|
665
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
666
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
667
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
668
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
669
|
+
[counter]="props()?.counter ?? false"
|
|
670
|
+
[color]="effectiveColor()"
|
|
671
|
+
[fill]="effectiveFill()"
|
|
672
|
+
[shape]="effectiveShape()"
|
|
673
|
+
[readonly]="f().readonly()"
|
|
674
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
675
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
676
|
+
[attr.tabindex]="tabIndex()"
|
|
677
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
678
|
+
[attr.aria-required]="ariaRequired"
|
|
679
|
+
[class.ion-invalid]="f().invalid()"
|
|
680
|
+
[class.ion-touched]="f().touched()"
|
|
681
|
+
>
|
|
682
|
+
<div slot="error">
|
|
683
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
684
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
685
|
+
}
|
|
686
|
+
</div>
|
|
687
|
+
</ion-input>
|
|
688
|
+
}
|
|
689
|
+
@case ('password') {
|
|
690
|
+
<ion-input
|
|
691
|
+
type="password"
|
|
692
|
+
[field]="f"
|
|
693
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
694
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
695
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
696
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
697
|
+
[counter]="props()?.counter ?? false"
|
|
698
|
+
[color]="effectiveColor()"
|
|
699
|
+
[fill]="effectiveFill()"
|
|
700
|
+
[shape]="effectiveShape()"
|
|
701
|
+
[readonly]="f().readonly()"
|
|
702
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
703
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
704
|
+
[attr.tabindex]="tabIndex()"
|
|
705
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
706
|
+
[attr.aria-required]="ariaRequired"
|
|
707
|
+
[class.ion-invalid]="f().invalid()"
|
|
708
|
+
[class.ion-touched]="f().touched()"
|
|
709
|
+
>
|
|
710
|
+
<div slot="error">
|
|
711
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
712
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
713
|
+
}
|
|
714
|
+
</div>
|
|
715
|
+
</ion-input>
|
|
716
|
+
}
|
|
717
|
+
@case ('number') {
|
|
718
|
+
<ion-input
|
|
719
|
+
type="number"
|
|
720
|
+
[field]="f"
|
|
721
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
722
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
723
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
724
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
725
|
+
[counter]="props()?.counter ?? false"
|
|
726
|
+
[color]="effectiveColor()"
|
|
727
|
+
[fill]="effectiveFill()"
|
|
728
|
+
[shape]="effectiveShape()"
|
|
729
|
+
[readonly]="f().readonly()"
|
|
730
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
731
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
732
|
+
[attr.tabindex]="tabIndex()"
|
|
733
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
734
|
+
[attr.aria-required]="ariaRequired"
|
|
735
|
+
[class.ion-invalid]="f().invalid()"
|
|
736
|
+
[class.ion-touched]="f().touched()"
|
|
737
|
+
>
|
|
738
|
+
<div slot="error">
|
|
739
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
740
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
741
|
+
}
|
|
742
|
+
</div>
|
|
743
|
+
</ion-input>
|
|
744
|
+
}
|
|
745
|
+
@case ('tel') {
|
|
746
|
+
<ion-input
|
|
747
|
+
type="tel"
|
|
748
|
+
[field]="f"
|
|
749
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
750
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
751
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
752
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
753
|
+
[counter]="props()?.counter ?? false"
|
|
754
|
+
[color]="effectiveColor()"
|
|
755
|
+
[fill]="effectiveFill()"
|
|
756
|
+
[shape]="effectiveShape()"
|
|
757
|
+
[readonly]="f().readonly()"
|
|
758
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
759
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
760
|
+
[attr.tabindex]="tabIndex()"
|
|
761
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
762
|
+
[attr.aria-required]="ariaRequired"
|
|
763
|
+
[class.ion-invalid]="f().invalid()"
|
|
764
|
+
[class.ion-touched]="f().touched()"
|
|
765
|
+
>
|
|
766
|
+
<div slot="error">
|
|
767
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
768
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
769
|
+
}
|
|
770
|
+
</div>
|
|
771
|
+
</ion-input>
|
|
772
|
+
}
|
|
773
|
+
@case ('url') {
|
|
774
|
+
<ion-input
|
|
775
|
+
type="url"
|
|
776
|
+
[field]="f"
|
|
777
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
778
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
779
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
780
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
781
|
+
[counter]="props()?.counter ?? false"
|
|
782
|
+
[color]="effectiveColor()"
|
|
783
|
+
[fill]="effectiveFill()"
|
|
784
|
+
[shape]="effectiveShape()"
|
|
785
|
+
[readonly]="f().readonly()"
|
|
786
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
787
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
788
|
+
[attr.tabindex]="tabIndex()"
|
|
789
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
790
|
+
[attr.aria-required]="ariaRequired"
|
|
791
|
+
[class.ion-invalid]="f().invalid()"
|
|
792
|
+
[class.ion-touched]="f().touched()"
|
|
793
|
+
>
|
|
794
|
+
<div slot="error">
|
|
795
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
796
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
797
|
+
}
|
|
798
|
+
</div>
|
|
799
|
+
</ion-input>
|
|
800
|
+
}
|
|
801
|
+
@default {
|
|
802
|
+
<ion-input
|
|
803
|
+
type="text"
|
|
804
|
+
[field]="f"
|
|
805
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
806
|
+
[labelPlacement]="effectiveLabelPlacement()"
|
|
807
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
808
|
+
[clearInput]="props()?.clearInput ?? false"
|
|
809
|
+
[counter]="props()?.counter ?? false"
|
|
810
|
+
[color]="effectiveColor()"
|
|
811
|
+
[fill]="effectiveFill()"
|
|
812
|
+
[shape]="effectiveShape()"
|
|
813
|
+
[readonly]="f().readonly()"
|
|
814
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
815
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
816
|
+
[attr.tabindex]="tabIndex()"
|
|
817
|
+
[attr.aria-invalid]="ariaInvalid"
|
|
818
|
+
[attr.aria-required]="ariaRequired"
|
|
819
|
+
[class.ion-invalid]="f().invalid()"
|
|
820
|
+
[class.ion-touched]="f().touched()"
|
|
821
|
+
>
|
|
822
|
+
<div slot="error">
|
|
823
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
824
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
825
|
+
}
|
|
826
|
+
</div>
|
|
827
|
+
</ion-input>
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
831
|
+
'[id]': '`${key()}`',
|
|
832
|
+
'[attr.data-testid]': 'key()',
|
|
833
|
+
'[class]': 'className()',
|
|
834
|
+
'[attr.hidden]': 'field()().hidden() || null',
|
|
835
|
+
}, styles: [":host([hidden]){display:none!important}\n"] }]
|
|
836
|
+
}], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
837
|
+
|
|
838
|
+
var ionicInput_component = /*#__PURE__*/Object.freeze({
|
|
839
|
+
__proto__: null,
|
|
840
|
+
default: IonicInputFieldComponent
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
class ValueInArrayPipe {
|
|
844
|
+
transform(element, array) {
|
|
845
|
+
return array?.includes(element) ?? false;
|
|
846
|
+
}
|
|
847
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: ValueInArrayPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
848
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.1", ngImport: i0, type: ValueInArrayPipe, isStandalone: true, name: "inArray" });
|
|
849
|
+
}
|
|
850
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: ValueInArrayPipe, decorators: [{
|
|
851
|
+
type: Pipe,
|
|
852
|
+
args: [{
|
|
853
|
+
pure: true,
|
|
854
|
+
name: 'inArray',
|
|
855
|
+
}]
|
|
856
|
+
}] });
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* Performs a deep equality comparison between two values
|
|
860
|
+
*/
|
|
861
|
+
function isEqual(a, b) {
|
|
862
|
+
if (a === b)
|
|
863
|
+
return true;
|
|
864
|
+
if (a == null || b == null)
|
|
865
|
+
return false;
|
|
866
|
+
if (typeof a !== typeof b)
|
|
867
|
+
return false;
|
|
868
|
+
if (a instanceof Date && b instanceof Date) {
|
|
869
|
+
return a.getTime() === b.getTime();
|
|
870
|
+
}
|
|
871
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
872
|
+
if (a.length !== b.length)
|
|
873
|
+
return false;
|
|
874
|
+
return a.every((item, index) => isEqual(item, b[index]));
|
|
875
|
+
}
|
|
876
|
+
if (typeof a === 'object' && typeof b === 'object') {
|
|
877
|
+
const keysA = Object.keys(a);
|
|
878
|
+
const keysB = Object.keys(b);
|
|
879
|
+
if (keysA.length !== keysB.length)
|
|
880
|
+
return false;
|
|
881
|
+
return keysA.every((key) => keysB.includes(key) && isEqual(a[key], b[key]));
|
|
882
|
+
}
|
|
883
|
+
return Object.is(a, b);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
class IonicMultiCheckboxFieldComponent {
|
|
887
|
+
field = input.required({ ...(ngDevMode ? { debugName: "field" } : {}) });
|
|
888
|
+
key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}) });
|
|
889
|
+
label = input(undefined, { ...(ngDevMode ? { debugName: "label" } : {}) });
|
|
890
|
+
placeholder = input(undefined, { ...(ngDevMode ? { debugName: "placeholder" } : {}) });
|
|
891
|
+
className = input('', { ...(ngDevMode ? { debugName: "className" } : {}) });
|
|
892
|
+
tabIndex = input(undefined, { ...(ngDevMode ? { debugName: "tabIndex" } : {}) });
|
|
893
|
+
options = input([], { ...(ngDevMode ? { debugName: "options" } : {}) });
|
|
894
|
+
props = input(undefined, { ...(ngDevMode ? { debugName: "props" } : {}) });
|
|
895
|
+
validationMessages = input(undefined, { ...(ngDevMode ? { debugName: "validationMessages" } : {}) });
|
|
896
|
+
defaultValidationMessages = input(undefined, { ...(ngDevMode ? { debugName: "defaultValidationMessages" } : {}) });
|
|
897
|
+
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
898
|
+
showErrors = shouldShowErrors(this.field);
|
|
899
|
+
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), { ...(ngDevMode ? { debugName: "errorsToDisplay" } : {}) });
|
|
900
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
901
|
+
// Accessibility
|
|
902
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
903
|
+
/** Base ID for error elements */
|
|
904
|
+
errorId = computed(() => `${this.key()}-error`, { ...(ngDevMode ? { debugName: "errorId" } : {}) });
|
|
905
|
+
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
906
|
+
isAriaInvalid = computed(() => {
|
|
907
|
+
const fieldState = this.field()();
|
|
908
|
+
return fieldState.invalid() && fieldState.touched();
|
|
909
|
+
}, { ...(ngDevMode ? { debugName: "isAriaInvalid" } : {}) });
|
|
910
|
+
/** Whether the field has a required validator */
|
|
911
|
+
isRequired = computed(() => {
|
|
912
|
+
return this.field()().required?.() === true;
|
|
913
|
+
}, { ...(ngDevMode ? { debugName: "isRequired" } : {}) });
|
|
914
|
+
valueViewModel = linkedSignal(() => {
|
|
915
|
+
const currentValues = this.field()().value();
|
|
916
|
+
return this.options().filter((option) => currentValues.includes(option.value));
|
|
917
|
+
}, { ...(ngDevMode ? { debugName: "valueViewModel" } : {}), equal: isEqual });
|
|
918
|
+
constructor() {
|
|
919
|
+
explicitEffect([this.valueViewModel], ([selectedOptions]) => {
|
|
920
|
+
const selectedValues = selectedOptions.map((option) => option.value);
|
|
921
|
+
if (!isEqual(selectedValues, this.field()().value())) {
|
|
922
|
+
this.field()().value.set(selectedValues);
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
explicitEffect([this.options], ([options]) => {
|
|
926
|
+
const values = options.map((option) => option.value);
|
|
927
|
+
const uniqueValues = new Set(values);
|
|
928
|
+
if (values.length !== uniqueValues.size) {
|
|
929
|
+
const duplicates = values.filter((value, index) => values.indexOf(value) !== index);
|
|
930
|
+
throw new Error(`Duplicate option values detected in ionic-multi-checkbox: ${duplicates.join(', ')}`);
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
onCheckboxChange(option, checked) {
|
|
935
|
+
this.valueViewModel.update((currentOptions) => {
|
|
936
|
+
if (checked) {
|
|
937
|
+
return currentOptions.some((opt) => opt.value === option.value) ? currentOptions : [...currentOptions, option];
|
|
938
|
+
}
|
|
939
|
+
else {
|
|
940
|
+
return currentOptions.filter((opt) => opt.value !== option.value);
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicMultiCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
945
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: IonicMultiCheckboxFieldComponent, isStandalone: true, selector: "df-ionic-multi-checkbox", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className() || \"\"", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, providers: [ValueInArrayPipe], ngImport: i0, template: `
|
|
946
|
+
@let f = field();
|
|
947
|
+
@if (label(); as label) {
|
|
948
|
+
<div class="checkbox-group-label">{{ label | dynamicText | async }}</div>
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
<div class="checkbox-group" role="group" [attr.aria-invalid]="isAriaInvalid()" [attr.aria-required]="isRequired() || null">
|
|
952
|
+
@for (option of options(); track option.value) {
|
|
953
|
+
<ion-item lines="none">
|
|
954
|
+
<ion-checkbox
|
|
955
|
+
[checked]="option | inArray: valueViewModel()"
|
|
956
|
+
[disabled]="f().disabled() || option.disabled"
|
|
957
|
+
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
958
|
+
[justify]="props()?.justify ?? 'start'"
|
|
959
|
+
[color]="props()?.color ?? 'primary'"
|
|
960
|
+
(ionChange)="onCheckboxChange(option, $event.detail.checked)"
|
|
961
|
+
>
|
|
962
|
+
{{ option.label | dynamicText | async }}
|
|
963
|
+
</ion-checkbox>
|
|
964
|
+
</ion-item>
|
|
965
|
+
}
|
|
966
|
+
</div>
|
|
967
|
+
|
|
968
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
969
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
970
|
+
}
|
|
971
|
+
`, isInline: true, styles: [":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: "pipe", type: ValueInArrayPipe, name: "inArray" }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
972
|
+
}
|
|
973
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicMultiCheckboxFieldComponent, decorators: [{
|
|
974
|
+
type: Component,
|
|
975
|
+
args: [{ selector: 'df-ionic-multi-checkbox', imports: [IonCheckbox, IonItem, IonNote, ValueInArrayPipe, DynamicTextPipe, AsyncPipe], template: `
|
|
976
|
+
@let f = field();
|
|
977
|
+
@if (label(); as label) {
|
|
978
|
+
<div class="checkbox-group-label">{{ label | dynamicText | async }}</div>
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
<div class="checkbox-group" role="group" [attr.aria-invalid]="isAriaInvalid()" [attr.aria-required]="isRequired() || null">
|
|
982
|
+
@for (option of options(); track option.value) {
|
|
983
|
+
<ion-item lines="none">
|
|
984
|
+
<ion-checkbox
|
|
985
|
+
[checked]="option | inArray: valueViewModel()"
|
|
986
|
+
[disabled]="f().disabled() || option.disabled"
|
|
987
|
+
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
988
|
+
[justify]="props()?.justify ?? 'start'"
|
|
989
|
+
[color]="props()?.color ?? 'primary'"
|
|
990
|
+
(ionChange)="onCheckboxChange(option, $event.detail.checked)"
|
|
991
|
+
>
|
|
992
|
+
{{ option.label | dynamicText | async }}
|
|
993
|
+
</ion-checkbox>
|
|
994
|
+
</ion-item>
|
|
995
|
+
}
|
|
996
|
+
</div>
|
|
997
|
+
|
|
998
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
999
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
1000
|
+
}
|
|
1001
|
+
`, host: {
|
|
1002
|
+
'[class]': 'className() || ""',
|
|
1003
|
+
'[id]': '`${key()}`',
|
|
1004
|
+
'[attr.data-testid]': 'key()',
|
|
1005
|
+
'[attr.hidden]': 'field()().hidden() || null',
|
|
1006
|
+
}, providers: [ValueInArrayPipe], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":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"] }]
|
|
1007
|
+
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
1008
|
+
|
|
1009
|
+
var ionicMultiCheckbox_component = /*#__PURE__*/Object.freeze({
|
|
1010
|
+
__proto__: null,
|
|
1011
|
+
default: IonicMultiCheckboxFieldComponent
|
|
1012
|
+
});
|
|
1013
|
+
|
|
1014
|
+
class IonicRadioFieldComponent {
|
|
1015
|
+
field = input.required({ ...(ngDevMode ? { debugName: "field" } : {}) });
|
|
1016
|
+
key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}) });
|
|
1017
|
+
// Properties
|
|
1018
|
+
label = input(undefined, { ...(ngDevMode ? { debugName: "label" } : {}) });
|
|
1019
|
+
placeholder = input(undefined, { ...(ngDevMode ? { debugName: "placeholder" } : {}) });
|
|
1020
|
+
className = input('', { ...(ngDevMode ? { debugName: "className" } : {}) });
|
|
1021
|
+
tabIndex = input(undefined, { ...(ngDevMode ? { debugName: "tabIndex" } : {}) });
|
|
1022
|
+
options = input([], { ...(ngDevMode ? { debugName: "options" } : {}) });
|
|
1023
|
+
props = input(undefined, { ...(ngDevMode ? { debugName: "props" } : {}) });
|
|
1024
|
+
validationMessages = input(undefined, { ...(ngDevMode ? { debugName: "validationMessages" } : {}) });
|
|
1025
|
+
defaultValidationMessages = input(undefined, { ...(ngDevMode ? { debugName: "defaultValidationMessages" } : {}) });
|
|
1026
|
+
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
1027
|
+
showErrors = shouldShowErrors(this.field);
|
|
1028
|
+
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), { ...(ngDevMode ? { debugName: "errorsToDisplay" } : {}) });
|
|
1029
|
+
defaultCompare = Object.is;
|
|
1030
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1031
|
+
// Accessibility
|
|
1032
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1033
|
+
/** Base ID for error elements */
|
|
1034
|
+
errorId = computed(() => `${this.key()}-error`, { ...(ngDevMode ? { debugName: "errorId" } : {}) });
|
|
1035
|
+
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
1036
|
+
isAriaInvalid = computed(() => {
|
|
1037
|
+
const fieldState = this.field()();
|
|
1038
|
+
return fieldState.invalid() && fieldState.touched();
|
|
1039
|
+
}, { ...(ngDevMode ? { debugName: "isAriaInvalid" } : {}) });
|
|
1040
|
+
/** Whether the field has a required validator */
|
|
1041
|
+
isRequired = computed(() => {
|
|
1042
|
+
return this.field()().required?.() === true;
|
|
1043
|
+
}, { ...(ngDevMode ? { debugName: "isRequired" } : {}) });
|
|
1044
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicRadioFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1045
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: IonicRadioFieldComponent, isStandalone: true, selector: "df-ionic-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 }, 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: `
|
|
1046
|
+
@let f = field();
|
|
1047
|
+
@if (label(); as label) {
|
|
1048
|
+
<div class="radio-label">{{ label | dynamicText | async }}</div>
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
<ion-radio-group
|
|
1052
|
+
[field]="f"
|
|
1053
|
+
[compareWith]="props()?.compareWith || defaultCompare"
|
|
1054
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
1055
|
+
[attr.aria-required]="isRequired() || null"
|
|
1056
|
+
>
|
|
1057
|
+
@for (option of options(); track option.value) {
|
|
1058
|
+
<ion-item [lines]="'none'">
|
|
1059
|
+
<ion-radio
|
|
1060
|
+
[value]="option.value"
|
|
1061
|
+
[disabled]="option.disabled || false"
|
|
1062
|
+
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
1063
|
+
[justify]="props()?.justify"
|
|
1064
|
+
[color]="props()?.color ?? 'primary'"
|
|
1065
|
+
>
|
|
1066
|
+
{{ option.label | dynamicText | async }}
|
|
1067
|
+
</ion-radio>
|
|
1068
|
+
</ion-item>
|
|
1069
|
+
}
|
|
1070
|
+
</ion-radio-group>
|
|
1071
|
+
|
|
1072
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1073
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
1074
|
+
}
|
|
1075
|
+
`, isInline: true, styles: [":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: Field, selector: "[field]", inputs: ["field"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1076
|
+
}
|
|
1077
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicRadioFieldComponent, decorators: [{
|
|
1078
|
+
type: Component,
|
|
1079
|
+
args: [{ selector: 'df-ionic-radio', imports: [IonRadioGroup, IonRadio, IonItem, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
|
|
1080
|
+
@let f = field();
|
|
1081
|
+
@if (label(); as label) {
|
|
1082
|
+
<div class="radio-label">{{ label | dynamicText | async }}</div>
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
<ion-radio-group
|
|
1086
|
+
[field]="f"
|
|
1087
|
+
[compareWith]="props()?.compareWith || defaultCompare"
|
|
1088
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
1089
|
+
[attr.aria-required]="isRequired() || null"
|
|
1090
|
+
>
|
|
1091
|
+
@for (option of options(); track option.value) {
|
|
1092
|
+
<ion-item [lines]="'none'">
|
|
1093
|
+
<ion-radio
|
|
1094
|
+
[value]="option.value"
|
|
1095
|
+
[disabled]="option.disabled || false"
|
|
1096
|
+
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
1097
|
+
[justify]="props()?.justify"
|
|
1098
|
+
[color]="props()?.color ?? 'primary'"
|
|
1099
|
+
>
|
|
1100
|
+
{{ option.label | dynamicText | async }}
|
|
1101
|
+
</ion-radio>
|
|
1102
|
+
</ion-item>
|
|
1103
|
+
}
|
|
1104
|
+
</ion-radio-group>
|
|
1105
|
+
|
|
1106
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1107
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
1108
|
+
}
|
|
1109
|
+
`, host: {
|
|
1110
|
+
'[class]': 'className()',
|
|
1111
|
+
'[id]': '`${key()}`',
|
|
1112
|
+
'[attr.data-testid]': 'key()',
|
|
1113
|
+
'[attr.hidden]': 'field()().hidden() || null',
|
|
1114
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":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"] }]
|
|
1115
|
+
}], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
1116
|
+
|
|
1117
|
+
var ionicRadio_component = /*#__PURE__*/Object.freeze({
|
|
1118
|
+
__proto__: null,
|
|
1119
|
+
default: IonicRadioFieldComponent
|
|
1120
|
+
});
|
|
1121
|
+
|
|
1122
|
+
class IonicSelectFieldComponent {
|
|
1123
|
+
field = input.required({ ...(ngDevMode ? { debugName: "field" } : {}) });
|
|
1124
|
+
key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}) });
|
|
1125
|
+
label = input(undefined, { ...(ngDevMode ? { debugName: "label" } : {}) });
|
|
1126
|
+
placeholder = input(undefined, { ...(ngDevMode ? { debugName: "placeholder" } : {}) });
|
|
1127
|
+
className = input('', { ...(ngDevMode ? { debugName: "className" } : {}) });
|
|
1128
|
+
tabIndex = input(undefined, { ...(ngDevMode ? { debugName: "tabIndex" } : {}) });
|
|
1129
|
+
options = input([], { ...(ngDevMode ? { debugName: "options" } : {}) });
|
|
1130
|
+
props = input(undefined, { ...(ngDevMode ? { debugName: "props" } : {}) });
|
|
1131
|
+
validationMessages = input(undefined, { ...(ngDevMode ? { debugName: "validationMessages" } : {}) });
|
|
1132
|
+
defaultValidationMessages = input(undefined, { ...(ngDevMode ? { debugName: "defaultValidationMessages" } : {}) });
|
|
1133
|
+
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
1134
|
+
showErrors = shouldShowErrors(this.field);
|
|
1135
|
+
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), { ...(ngDevMode ? { debugName: "errorsToDisplay" } : {}) });
|
|
1136
|
+
defaultCompare = Object.is;
|
|
1137
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1138
|
+
// Accessibility
|
|
1139
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1140
|
+
/** Base ID for error elements */
|
|
1141
|
+
errorId = computed(() => `${this.key()}-error`, { ...(ngDevMode ? { debugName: "errorId" } : {}) });
|
|
1142
|
+
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
1143
|
+
isAriaInvalid = computed(() => {
|
|
1144
|
+
const fieldState = this.field()();
|
|
1145
|
+
return fieldState.invalid() && fieldState.touched();
|
|
1146
|
+
}, { ...(ngDevMode ? { debugName: "isAriaInvalid" } : {}) });
|
|
1147
|
+
/** Whether the field has a required validator */
|
|
1148
|
+
isRequired = computed(() => {
|
|
1149
|
+
return this.field()().required?.() === true;
|
|
1150
|
+
}, { ...(ngDevMode ? { debugName: "isRequired" } : {}) });
|
|
1151
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1152
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: IonicSelectFieldComponent, isStandalone: true, selector: "df-ionic-select", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
|
|
1153
|
+
@let f = field();
|
|
1154
|
+
|
|
1155
|
+
<ion-select
|
|
1156
|
+
[field]="f"
|
|
1157
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
1158
|
+
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1159
|
+
[placeholder]="(placeholder() ?? props()?.placeholder | dynamicText | async) ?? ''"
|
|
1160
|
+
[multiple]="props()?.multiple ?? false"
|
|
1161
|
+
[compareWith]="props()?.compareWith ?? defaultCompare"
|
|
1162
|
+
[interface]="props()?.interface ?? 'alert'"
|
|
1163
|
+
[interfaceOptions]="props()?.interfaceOptions ?? {}"
|
|
1164
|
+
[cancelText]="props()?.cancelText ?? 'Cancel'"
|
|
1165
|
+
[okText]="props()?.okText ?? 'OK'"
|
|
1166
|
+
[color]="props()?.color"
|
|
1167
|
+
[fill]="props()?.fill ?? 'outline'"
|
|
1168
|
+
[shape]="props()?.shape"
|
|
1169
|
+
[attr.tabindex]="tabIndex()"
|
|
1170
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
1171
|
+
[attr.aria-required]="isRequired() || null"
|
|
1172
|
+
[class.ion-invalid]="f().invalid()"
|
|
1173
|
+
[class.ion-touched]="f().touched()"
|
|
1174
|
+
>
|
|
1175
|
+
@for (option of options(); track option.value) {
|
|
1176
|
+
<ion-select-option [value]="option.value" [disabled]="option.disabled || false">
|
|
1177
|
+
{{ option.label | dynamicText | async }}
|
|
1178
|
+
</ion-select-option>
|
|
1179
|
+
}
|
|
1180
|
+
<div slot="error">
|
|
1181
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1182
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
1183
|
+
}
|
|
1184
|
+
</div>
|
|
1185
|
+
</ion-select>
|
|
1186
|
+
`, isInline: true, styles: [":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: Field, selector: "[field]", inputs: ["field"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1187
|
+
}
|
|
1188
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicSelectFieldComponent, decorators: [{
|
|
1189
|
+
type: Component,
|
|
1190
|
+
args: [{ selector: 'df-ionic-select', imports: [IonSelect, IonSelectOption, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
|
|
1191
|
+
@let f = field();
|
|
1192
|
+
|
|
1193
|
+
<ion-select
|
|
1194
|
+
[field]="f"
|
|
1195
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
1196
|
+
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1197
|
+
[placeholder]="(placeholder() ?? props()?.placeholder | dynamicText | async) ?? ''"
|
|
1198
|
+
[multiple]="props()?.multiple ?? false"
|
|
1199
|
+
[compareWith]="props()?.compareWith ?? defaultCompare"
|
|
1200
|
+
[interface]="props()?.interface ?? 'alert'"
|
|
1201
|
+
[interfaceOptions]="props()?.interfaceOptions ?? {}"
|
|
1202
|
+
[cancelText]="props()?.cancelText ?? 'Cancel'"
|
|
1203
|
+
[okText]="props()?.okText ?? 'OK'"
|
|
1204
|
+
[color]="props()?.color"
|
|
1205
|
+
[fill]="props()?.fill ?? 'outline'"
|
|
1206
|
+
[shape]="props()?.shape"
|
|
1207
|
+
[attr.tabindex]="tabIndex()"
|
|
1208
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
1209
|
+
[attr.aria-required]="isRequired() || null"
|
|
1210
|
+
[class.ion-invalid]="f().invalid()"
|
|
1211
|
+
[class.ion-touched]="f().touched()"
|
|
1212
|
+
>
|
|
1213
|
+
@for (option of options(); track option.value) {
|
|
1214
|
+
<ion-select-option [value]="option.value" [disabled]="option.disabled || false">
|
|
1215
|
+
{{ option.label | dynamicText | async }}
|
|
1216
|
+
</ion-select-option>
|
|
1217
|
+
}
|
|
1218
|
+
<div slot="error">
|
|
1219
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1220
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
1221
|
+
}
|
|
1222
|
+
</div>
|
|
1223
|
+
</ion-select>
|
|
1224
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1225
|
+
'[id]': '`${key()}`',
|
|
1226
|
+
'[attr.data-testid]': 'key()',
|
|
1227
|
+
'[class]': 'className()',
|
|
1228
|
+
'[attr.hidden]': 'field()().hidden() || null',
|
|
1229
|
+
}, styles: [":host([hidden]){display:none!important}\n"] }]
|
|
1230
|
+
}], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
1231
|
+
|
|
1232
|
+
var ionicSelect_component = /*#__PURE__*/Object.freeze({
|
|
1233
|
+
__proto__: null,
|
|
1234
|
+
default: IonicSelectFieldComponent
|
|
1235
|
+
});
|
|
1236
|
+
|
|
1237
|
+
class IonicSliderFieldComponent {
|
|
1238
|
+
field = input.required({ ...(ngDevMode ? { debugName: "field" } : {}) });
|
|
1239
|
+
key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}) });
|
|
1240
|
+
label = input(undefined, { ...(ngDevMode ? { debugName: "label" } : {}) });
|
|
1241
|
+
placeholder = input(undefined, { ...(ngDevMode ? { debugName: "placeholder" } : {}) });
|
|
1242
|
+
className = input('', { ...(ngDevMode ? { debugName: "className" } : {}) });
|
|
1243
|
+
tabIndex = input(undefined, { ...(ngDevMode ? { debugName: "tabIndex" } : {}) });
|
|
1244
|
+
props = input(undefined, { ...(ngDevMode ? { debugName: "props" } : {}) });
|
|
1245
|
+
validationMessages = input(undefined, { ...(ngDevMode ? { debugName: "validationMessages" } : {}) });
|
|
1246
|
+
defaultValidationMessages = input(undefined, { ...(ngDevMode ? { debugName: "defaultValidationMessages" } : {}) });
|
|
1247
|
+
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
1248
|
+
showErrors = shouldShowErrors(this.field);
|
|
1249
|
+
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), { ...(ngDevMode ? { debugName: "errorsToDisplay" } : {}) });
|
|
1250
|
+
defaultPinFormatter = (value) => String(value);
|
|
1251
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1252
|
+
// Accessibility
|
|
1253
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1254
|
+
/** Base ID for error elements */
|
|
1255
|
+
errorId = computed(() => `${this.key()}-error`, { ...(ngDevMode ? { debugName: "errorId" } : {}) });
|
|
1256
|
+
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
1257
|
+
isAriaInvalid = computed(() => {
|
|
1258
|
+
const fieldState = this.field()();
|
|
1259
|
+
return fieldState.invalid() && fieldState.touched();
|
|
1260
|
+
}, { ...(ngDevMode ? { debugName: "isAriaInvalid" } : {}) });
|
|
1261
|
+
/** Whether the field has a required validator */
|
|
1262
|
+
isRequired = computed(() => {
|
|
1263
|
+
return this.field()().required?.() === true;
|
|
1264
|
+
}, { ...(ngDevMode ? { debugName: "isRequired" } : {}) });
|
|
1265
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicSliderFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1266
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: IonicSliderFieldComponent, isStandalone: true, selector: "df-ionic-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 }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
|
|
1267
|
+
@let f = field();
|
|
1268
|
+
|
|
1269
|
+
<ion-range
|
|
1270
|
+
[field]="f"
|
|
1271
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
1272
|
+
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1273
|
+
[step]="props()?.step ?? 1"
|
|
1274
|
+
[dualKnobs]="props()?.dualKnobs ?? false"
|
|
1275
|
+
[pin]="props()?.pin ?? false"
|
|
1276
|
+
[pinFormatter]="props()?.pinFormatter ?? defaultPinFormatter"
|
|
1277
|
+
[ticks]="props()?.ticks ?? false"
|
|
1278
|
+
[snaps]="props()?.snaps ?? false"
|
|
1279
|
+
[color]="props()?.color ?? 'primary'"
|
|
1280
|
+
[attr.tabindex]="tabIndex()"
|
|
1281
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
1282
|
+
[attr.aria-required]="isRequired() || null"
|
|
1283
|
+
/>
|
|
1284
|
+
|
|
1285
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1286
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
1287
|
+
}
|
|
1288
|
+
`, isInline: true, styles: [":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: Field, selector: "[field]", inputs: ["field"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1289
|
+
}
|
|
1290
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicSliderFieldComponent, decorators: [{
|
|
1291
|
+
type: Component,
|
|
1292
|
+
args: [{ selector: 'df-ionic-slider', imports: [IonRange, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
|
|
1293
|
+
@let f = field();
|
|
1294
|
+
|
|
1295
|
+
<ion-range
|
|
1296
|
+
[field]="f"
|
|
1297
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
1298
|
+
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1299
|
+
[step]="props()?.step ?? 1"
|
|
1300
|
+
[dualKnobs]="props()?.dualKnobs ?? false"
|
|
1301
|
+
[pin]="props()?.pin ?? false"
|
|
1302
|
+
[pinFormatter]="props()?.pinFormatter ?? defaultPinFormatter"
|
|
1303
|
+
[ticks]="props()?.ticks ?? false"
|
|
1304
|
+
[snaps]="props()?.snaps ?? false"
|
|
1305
|
+
[color]="props()?.color ?? 'primary'"
|
|
1306
|
+
[attr.tabindex]="tabIndex()"
|
|
1307
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
1308
|
+
[attr.aria-required]="isRequired() || null"
|
|
1309
|
+
/>
|
|
1310
|
+
|
|
1311
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1312
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
1313
|
+
}
|
|
1314
|
+
`, host: {
|
|
1315
|
+
'[class]': 'className()',
|
|
1316
|
+
'[id]': '`${key()}`',
|
|
1317
|
+
'[attr.data-testid]': 'key()',
|
|
1318
|
+
'[attr.hidden]': 'field()().hidden() || null',
|
|
1319
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}:host([hidden]){display:none!important}\n"] }]
|
|
1320
|
+
}], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
1321
|
+
|
|
1322
|
+
var ionicSlider_component = /*#__PURE__*/Object.freeze({
|
|
1323
|
+
__proto__: null,
|
|
1324
|
+
default: IonicSliderFieldComponent
|
|
1325
|
+
});
|
|
1326
|
+
|
|
1327
|
+
class IonicTextareaFieldComponent {
|
|
1328
|
+
field = input.required({ ...(ngDevMode ? { debugName: "field" } : {}) });
|
|
1329
|
+
key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}) });
|
|
1330
|
+
label = input(undefined, { ...(ngDevMode ? { debugName: "label" } : {}) });
|
|
1331
|
+
placeholder = input(undefined, { ...(ngDevMode ? { debugName: "placeholder" } : {}) });
|
|
1332
|
+
className = input('', { ...(ngDevMode ? { debugName: "className" } : {}) });
|
|
1333
|
+
tabIndex = input(undefined, { ...(ngDevMode ? { debugName: "tabIndex" } : {}) });
|
|
1334
|
+
props = input(undefined, { ...(ngDevMode ? { debugName: "props" } : {}) });
|
|
1335
|
+
validationMessages = input(undefined, { ...(ngDevMode ? { debugName: "validationMessages" } : {}) });
|
|
1336
|
+
defaultValidationMessages = input(undefined, { ...(ngDevMode ? { debugName: "defaultValidationMessages" } : {}) });
|
|
1337
|
+
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
1338
|
+
showErrors = shouldShowErrors(this.field);
|
|
1339
|
+
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), { ...(ngDevMode ? { debugName: "errorsToDisplay" } : {}) });
|
|
1340
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1341
|
+
// Accessibility
|
|
1342
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1343
|
+
/** Base ID for error elements */
|
|
1344
|
+
errorId = computed(() => `${this.key()}-error`, { ...(ngDevMode ? { debugName: "errorId" } : {}) });
|
|
1345
|
+
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
1346
|
+
isAriaInvalid = computed(() => {
|
|
1347
|
+
const fieldState = this.field()();
|
|
1348
|
+
return fieldState.invalid() && fieldState.touched();
|
|
1349
|
+
}, { ...(ngDevMode ? { debugName: "isAriaInvalid" } : {}) });
|
|
1350
|
+
/** Whether the field has a required validator */
|
|
1351
|
+
isRequired = computed(() => {
|
|
1352
|
+
return this.field()().required?.() === true;
|
|
1353
|
+
}, { ...(ngDevMode ? { debugName: "isRequired" } : {}) });
|
|
1354
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicTextareaFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1355
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: IonicTextareaFieldComponent, isStandalone: true, selector: "df-ionic-textarea", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
|
|
1356
|
+
@let f = field();
|
|
1357
|
+
|
|
1358
|
+
<ion-textarea
|
|
1359
|
+
[field]="f"
|
|
1360
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
1361
|
+
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1362
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1363
|
+
[rows]="props()?.rows ?? 4"
|
|
1364
|
+
[autoGrow]="props()?.autoGrow ?? false"
|
|
1365
|
+
[counter]="props()?.counter ?? false"
|
|
1366
|
+
[color]="props()?.color"
|
|
1367
|
+
[fill]="props()?.fill ?? 'outline'"
|
|
1368
|
+
[shape]="props()?.shape"
|
|
1369
|
+
[readonly]="f().readonly()"
|
|
1370
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
1371
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
1372
|
+
[attr.tabindex]="tabIndex()"
|
|
1373
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
1374
|
+
[attr.aria-required]="isRequired() || null"
|
|
1375
|
+
[class.ion-invalid]="f().invalid()"
|
|
1376
|
+
[class.ion-touched]="f().touched()"
|
|
1377
|
+
>
|
|
1378
|
+
<div slot="error">
|
|
1379
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1380
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
1381
|
+
}
|
|
1382
|
+
</div>
|
|
1383
|
+
</ion-textarea>
|
|
1384
|
+
`, isInline: true, styles: [":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: Field, selector: "[field]", inputs: ["field"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1385
|
+
}
|
|
1386
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicTextareaFieldComponent, decorators: [{
|
|
1387
|
+
type: Component,
|
|
1388
|
+
args: [{ selector: 'df-ionic-textarea', imports: [IonTextarea, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
|
|
1389
|
+
@let f = field();
|
|
1390
|
+
|
|
1391
|
+
<ion-textarea
|
|
1392
|
+
[field]="f"
|
|
1393
|
+
[label]="(label() | dynamicText | async) ?? undefined"
|
|
1394
|
+
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1395
|
+
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1396
|
+
[rows]="props()?.rows ?? 4"
|
|
1397
|
+
[autoGrow]="props()?.autoGrow ?? false"
|
|
1398
|
+
[counter]="props()?.counter ?? false"
|
|
1399
|
+
[color]="props()?.color"
|
|
1400
|
+
[fill]="props()?.fill ?? 'outline'"
|
|
1401
|
+
[shape]="props()?.shape"
|
|
1402
|
+
[readonly]="f().readonly()"
|
|
1403
|
+
[helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
|
|
1404
|
+
[errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
|
|
1405
|
+
[attr.tabindex]="tabIndex()"
|
|
1406
|
+
[attr.aria-invalid]="isAriaInvalid()"
|
|
1407
|
+
[attr.aria-required]="isRequired() || null"
|
|
1408
|
+
[class.ion-invalid]="f().invalid()"
|
|
1409
|
+
[class.ion-touched]="f().touched()"
|
|
1410
|
+
>
|
|
1411
|
+
<div slot="error">
|
|
1412
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1413
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
1414
|
+
}
|
|
1415
|
+
</div>
|
|
1416
|
+
</ion-textarea>
|
|
1417
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1418
|
+
'[id]': '`${key()}`',
|
|
1419
|
+
'[attr.data-testid]': 'key()',
|
|
1420
|
+
'[class]': 'className()',
|
|
1421
|
+
'[attr.hidden]': 'field()().hidden() || null',
|
|
1422
|
+
}, styles: [":host([hidden]){display:none!important}\n"] }]
|
|
1423
|
+
}], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
1424
|
+
|
|
1425
|
+
var ionicTextarea_component = /*#__PURE__*/Object.freeze({
|
|
1426
|
+
__proto__: null,
|
|
1427
|
+
default: IonicTextareaFieldComponent
|
|
1428
|
+
});
|
|
1429
|
+
|
|
1430
|
+
/**
|
|
1431
|
+
* A wrapper component for Ionic's ion-toggle that implements FormCheckboxControl.
|
|
1432
|
+
* This allows it to work with Angular's [field] directive from @angular/forms/signals.
|
|
1433
|
+
*
|
|
1434
|
+
* We use FormCheckboxControl because ion-toggle is a boolean checkbox-like control.
|
|
1435
|
+
* The Field directive binds to the `checked` model for checkbox controls.
|
|
1436
|
+
*/
|
|
1437
|
+
class IonicToggleControlComponent {
|
|
1438
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1439
|
+
// FormCheckboxControl implementation
|
|
1440
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1441
|
+
/** The checked state - required by FormCheckboxControl */
|
|
1442
|
+
checked = model(false, { ...(ngDevMode ? { debugName: "checked" } : {}) });
|
|
1443
|
+
/** Tracks whether the field has been touched - used by Field directive */
|
|
1444
|
+
touched = model(false, { ...(ngDevMode ? { debugName: "touched" } : {}) });
|
|
1445
|
+
/** Whether the field is disabled */
|
|
1446
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : {}) });
|
|
1447
|
+
/** Whether the field is readonly */
|
|
1448
|
+
readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : {}) });
|
|
1449
|
+
/** Whether the field is invalid (from Field directive) */
|
|
1450
|
+
invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : {}) });
|
|
1451
|
+
/** Whether the field is required (from Field directive) */
|
|
1452
|
+
required = input(false, { ...(ngDevMode ? { debugName: "required" } : {}) });
|
|
1453
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1454
|
+
// Ionic-specific props
|
|
1455
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1456
|
+
labelPlacement = input('end', { ...(ngDevMode ? { debugName: "labelPlacement" } : {}) });
|
|
1457
|
+
justify = input(undefined, { ...(ngDevMode ? { debugName: "justify" } : {}) });
|
|
1458
|
+
color = input('primary', { ...(ngDevMode ? { debugName: "color" } : {}) });
|
|
1459
|
+
enableOnOffLabels = input(false, { ...(ngDevMode ? { debugName: "enableOnOffLabels" } : {}) });
|
|
1460
|
+
tabIndex = input(undefined, { ...(ngDevMode ? { debugName: "tabIndex" } : {}) });
|
|
1461
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1462
|
+
// Computed ARIA attributes
|
|
1463
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1464
|
+
/** aria-invalid: true when field is invalid AND touched */
|
|
1465
|
+
ariaInvalid = computed(() => {
|
|
1466
|
+
return this.invalid() && this.touched();
|
|
1467
|
+
}, { ...(ngDevMode ? { debugName: "ariaInvalid" } : {}) });
|
|
1468
|
+
/** aria-required: true if field is required, null otherwise */
|
|
1469
|
+
ariaRequired = computed(() => {
|
|
1470
|
+
return this.required() ? true : null;
|
|
1471
|
+
}, { ...(ngDevMode ? { debugName: "ariaRequired" } : {}) });
|
|
1472
|
+
/** aria-readonly: true if field is readonly, null otherwise */
|
|
1473
|
+
ariaReadonly = computed(() => {
|
|
1474
|
+
return this.readonly() ? true : null;
|
|
1475
|
+
}, { ...(ngDevMode ? { debugName: "ariaReadonly" } : {}) });
|
|
1476
|
+
/** Computed checked state - ensures proper boolean conversion for ion-toggle */
|
|
1477
|
+
isChecked = computed(() => {
|
|
1478
|
+
return this.checked() === true;
|
|
1479
|
+
}, { ...(ngDevMode ? { debugName: "isChecked" } : {}) });
|
|
1480
|
+
/**
|
|
1481
|
+
* ion-toggle doesn't have a native readonly attribute.
|
|
1482
|
+
* When readonly, we disable the toggle to prevent changes while maintaining the visual state.
|
|
1483
|
+
*/
|
|
1484
|
+
isEffectivelyDisabled = computed(() => {
|
|
1485
|
+
return this.disabled() || this.readonly();
|
|
1486
|
+
}, { ...(ngDevMode ? { debugName: "isEffectivelyDisabled" } : {}) });
|
|
1487
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1488
|
+
// Event Handlers
|
|
1489
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1490
|
+
/** Handle toggle change - sync ion-toggle's checked state to our checked model */
|
|
1491
|
+
onToggleChange(event) {
|
|
1492
|
+
this.checked.set(event.detail.checked);
|
|
1493
|
+
}
|
|
1494
|
+
/** Marks the field as touched when toggle loses focus */
|
|
1495
|
+
onBlur() {
|
|
1496
|
+
this.touched.set(true);
|
|
1497
|
+
}
|
|
1498
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicToggleControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1499
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.1", type: IonicToggleControlComponent, isStandalone: true, selector: "df-ionic-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" }, ngImport: i0, template: `
|
|
1500
|
+
<ion-toggle
|
|
1501
|
+
[checked]="isChecked()"
|
|
1502
|
+
(ionChange)="onToggleChange($event)"
|
|
1503
|
+
(ionBlur)="onBlur()"
|
|
1504
|
+
[labelPlacement]="labelPlacement()"
|
|
1505
|
+
[justify]="justify()"
|
|
1506
|
+
[color]="color()"
|
|
1507
|
+
[enableOnOffLabels]="enableOnOffLabels()"
|
|
1508
|
+
[disabled]="isEffectivelyDisabled()"
|
|
1509
|
+
[attr.tabindex]="tabIndex()"
|
|
1510
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1511
|
+
[attr.aria-required]="ariaRequired()"
|
|
1512
|
+
[attr.aria-readonly]="ariaReadonly()"
|
|
1513
|
+
>
|
|
1514
|
+
<ng-content />
|
|
1515
|
+
</ion-toggle>
|
|
1516
|
+
`, isInline: true, dependencies: [{ kind: "component", type: IonToggle, selector: "ion-toggle", inputs: ["checked", "color", "disabled", "enableOnOffLabels", "errorText", "helperText", "justify", "labelPlacement", "mode", "name", "value"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1517
|
+
}
|
|
1518
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicToggleControlComponent, decorators: [{
|
|
1519
|
+
type: Component,
|
|
1520
|
+
args: [{
|
|
1521
|
+
selector: 'df-ionic-toggle-control',
|
|
1522
|
+
imports: [IonToggle],
|
|
1523
|
+
template: `
|
|
1524
|
+
<ion-toggle
|
|
1525
|
+
[checked]="isChecked()"
|
|
1526
|
+
(ionChange)="onToggleChange($event)"
|
|
1527
|
+
(ionBlur)="onBlur()"
|
|
1528
|
+
[labelPlacement]="labelPlacement()"
|
|
1529
|
+
[justify]="justify()"
|
|
1530
|
+
[color]="color()"
|
|
1531
|
+
[enableOnOffLabels]="enableOnOffLabels()"
|
|
1532
|
+
[disabled]="isEffectivelyDisabled()"
|
|
1533
|
+
[attr.tabindex]="tabIndex()"
|
|
1534
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1535
|
+
[attr.aria-required]="ariaRequired()"
|
|
1536
|
+
[attr.aria-readonly]="ariaReadonly()"
|
|
1537
|
+
>
|
|
1538
|
+
<ng-content />
|
|
1539
|
+
</ion-toggle>
|
|
1540
|
+
`,
|
|
1541
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1542
|
+
}]
|
|
1543
|
+
}], 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 }] }] } });
|
|
1544
|
+
|
|
1545
|
+
class IonicToggleFieldComponent {
|
|
1546
|
+
field = input.required({ ...(ngDevMode ? { debugName: "field" } : {}) });
|
|
1547
|
+
key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}) });
|
|
1548
|
+
// Properties
|
|
1549
|
+
label = input(undefined, { ...(ngDevMode ? { debugName: "label" } : {}) });
|
|
1550
|
+
placeholder = input(undefined, { ...(ngDevMode ? { debugName: "placeholder" } : {}) });
|
|
1551
|
+
className = input('', { ...(ngDevMode ? { debugName: "className" } : {}) });
|
|
1552
|
+
tabIndex = input(undefined, { ...(ngDevMode ? { debugName: "tabIndex" } : {}) });
|
|
1553
|
+
props = input(undefined, { ...(ngDevMode ? { debugName: "props" } : {}) });
|
|
1554
|
+
validationMessages = input(undefined, { ...(ngDevMode ? { debugName: "validationMessages" } : {}) });
|
|
1555
|
+
defaultValidationMessages = input(undefined, { ...(ngDevMode ? { debugName: "defaultValidationMessages" } : {}) });
|
|
1556
|
+
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
1557
|
+
showErrors = shouldShowErrors(this.field);
|
|
1558
|
+
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), { ...(ngDevMode ? { debugName: "errorsToDisplay" } : {}) });
|
|
1559
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1560
|
+
// Accessibility
|
|
1561
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1562
|
+
/** Base ID for error elements */
|
|
1563
|
+
errorId = computed(() => `${this.key()}-error`, { ...(ngDevMode ? { debugName: "errorId" } : {}) });
|
|
1564
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicToggleFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1565
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: IonicToggleFieldComponent, isStandalone: true, selector: "df-ionic-toggle", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
|
|
1566
|
+
@let f = field();
|
|
1567
|
+
|
|
1568
|
+
<df-ionic-toggle-control
|
|
1569
|
+
[field]="f"
|
|
1570
|
+
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
1571
|
+
[justify]="props()?.justify"
|
|
1572
|
+
[color]="props()?.color ?? 'primary'"
|
|
1573
|
+
[enableOnOffLabels]="props()?.enableOnOffLabels ?? false"
|
|
1574
|
+
[tabIndex]="tabIndex()"
|
|
1575
|
+
>
|
|
1576
|
+
{{ label() | dynamicText | async }}
|
|
1577
|
+
</df-ionic-toggle-control>
|
|
1578
|
+
|
|
1579
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1580
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
1581
|
+
}
|
|
1582
|
+
`, isInline: true, styles: [":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonicToggleControlComponent, selector: "df-ionic-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: Field, selector: "[field]", inputs: ["field"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1583
|
+
}
|
|
1584
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: IonicToggleFieldComponent, decorators: [{
|
|
1585
|
+
type: Component,
|
|
1586
|
+
args: [{ selector: 'df-ionic-toggle', imports: [IonicToggleControlComponent, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
|
|
1587
|
+
@let f = field();
|
|
1588
|
+
|
|
1589
|
+
<df-ionic-toggle-control
|
|
1590
|
+
[field]="f"
|
|
1591
|
+
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
1592
|
+
[justify]="props()?.justify"
|
|
1593
|
+
[color]="props()?.color ?? 'primary'"
|
|
1594
|
+
[enableOnOffLabels]="props()?.enableOnOffLabels ?? false"
|
|
1595
|
+
[tabIndex]="tabIndex()"
|
|
1596
|
+
>
|
|
1597
|
+
{{ label() | dynamicText | async }}
|
|
1598
|
+
</df-ionic-toggle-control>
|
|
1599
|
+
|
|
1600
|
+
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1601
|
+
<ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
|
|
1602
|
+
}
|
|
1603
|
+
`, host: {
|
|
1604
|
+
'[class]': 'className()',
|
|
1605
|
+
'[id]': '`${key()}`',
|
|
1606
|
+
'[attr.data-testid]': 'key()',
|
|
1607
|
+
'[attr.hidden]': 'field()().hidden() || null',
|
|
1608
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}:host([hidden]){display:none!important}\n"] }]
|
|
1609
|
+
}], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
1610
|
+
|
|
1611
|
+
var ionicToggle_component = /*#__PURE__*/Object.freeze({
|
|
1612
|
+
__proto__: null,
|
|
1613
|
+
default: IonicToggleFieldComponent
|
|
1614
|
+
});
|
|
1615
|
+
|
|
1616
|
+
// Public exports for ionic field fields and types
|
|
1617
|
+
// Button
|
|
1618
|
+
|
|
1619
|
+
/**
|
|
1620
|
+
* Ionic field type constants
|
|
1621
|
+
* Based on available field components in the /fields folder
|
|
1622
|
+
*/
|
|
1623
|
+
const IonicField = {
|
|
1624
|
+
Input: 'input',
|
|
1625
|
+
Select: 'select',
|
|
1626
|
+
Checkbox: 'checkbox',
|
|
1627
|
+
Button: 'button',
|
|
1628
|
+
Submit: 'submit',
|
|
1629
|
+
Next: 'next',
|
|
1630
|
+
Previous: 'previous',
|
|
1631
|
+
AddArrayItem: 'addArrayItem',
|
|
1632
|
+
RemoveArrayItem: 'removeArrayItem',
|
|
1633
|
+
Textarea: 'textarea',
|
|
1634
|
+
Radio: 'radio',
|
|
1635
|
+
MultiCheckbox: 'multi-checkbox',
|
|
1636
|
+
Datepicker: 'datepicker',
|
|
1637
|
+
Slider: 'slider',
|
|
1638
|
+
Toggle: 'toggle',
|
|
1639
|
+
};
|
|
1640
|
+
|
|
1641
|
+
/**
|
|
1642
|
+
* Generic button mapper for custom events or basic buttons.
|
|
1643
|
+
* For specific button types (submit, next, prev, add/remove array items),
|
|
1644
|
+
* use the dedicated field types and their specific mappers.
|
|
1645
|
+
*
|
|
1646
|
+
* @param fieldDef The button field definition
|
|
1647
|
+
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1648
|
+
*/
|
|
1649
|
+
function buttonFieldMapper(fieldDef) {
|
|
1650
|
+
// Build base inputs (static, from field definition)
|
|
1651
|
+
const baseInputs = buildBaseInputs(fieldDef);
|
|
1652
|
+
return computed(() => {
|
|
1653
|
+
const inputs = {
|
|
1654
|
+
...baseInputs,
|
|
1655
|
+
};
|
|
1656
|
+
if (fieldDef.disabled !== undefined) {
|
|
1657
|
+
inputs['disabled'] = fieldDef.disabled;
|
|
1658
|
+
}
|
|
1659
|
+
if (fieldDef.hidden !== undefined) {
|
|
1660
|
+
inputs['hidden'] = fieldDef.hidden;
|
|
1661
|
+
}
|
|
1662
|
+
// Add event binding for button events
|
|
1663
|
+
if ('event' in fieldDef && fieldDef.event !== undefined) {
|
|
1664
|
+
inputs['event'] = fieldDef.event;
|
|
1665
|
+
}
|
|
1666
|
+
// Add eventArgs binding if provided
|
|
1667
|
+
if ('eventArgs' in fieldDef && fieldDef.eventArgs !== undefined) {
|
|
1668
|
+
inputs['eventArgs'] = fieldDef.eventArgs;
|
|
1669
|
+
}
|
|
1670
|
+
return inputs;
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
/**
|
|
1675
|
+
* Mapper for submit button - configures native form submission via type="submit"
|
|
1676
|
+
*
|
|
1677
|
+
* Unlike other buttons, submit buttons don't dispatch events directly.
|
|
1678
|
+
* Instead, they trigger native form submission which the form component
|
|
1679
|
+
* intercepts and dispatches to the EventBus.
|
|
1680
|
+
*
|
|
1681
|
+
* Disabled state is resolved using the button-logic-resolver which considers:
|
|
1682
|
+
* 1. Explicit `disabled: true` on the field definition
|
|
1683
|
+
* 2. Field-level `logic` array (if present, overrides form-level defaults)
|
|
1684
|
+
* 3. Form-level `options.submitButton` defaults (disableWhenInvalid, disableWhileSubmitting)
|
|
1685
|
+
*
|
|
1686
|
+
* @param fieldDef The submit button field definition
|
|
1687
|
+
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1688
|
+
*/
|
|
1689
|
+
function submitButtonFieldMapper(fieldDef) {
|
|
1690
|
+
// Inject field signal context to access form state and options
|
|
1691
|
+
const fieldSignalContext = inject(FIELD_SIGNAL_CONTEXT);
|
|
1692
|
+
// Build base inputs (static, from field definition)
|
|
1693
|
+
const baseInputs = buildBaseInputs(fieldDef);
|
|
1694
|
+
// Use button-logic-resolver to compute disabled state
|
|
1695
|
+
const fieldWithLogic = fieldDef;
|
|
1696
|
+
const disabledSignal = resolveSubmitButtonDisabled({
|
|
1697
|
+
form: fieldSignalContext.form,
|
|
1698
|
+
formOptions: fieldSignalContext.formOptions,
|
|
1699
|
+
fieldLogic: fieldWithLogic.logic,
|
|
1700
|
+
explicitlyDisabled: fieldDef.disabled,
|
|
1701
|
+
});
|
|
1702
|
+
// Return computed signal - evaluates disabledSignal inside for reactivity
|
|
1703
|
+
return computed(() => {
|
|
1704
|
+
const inputs = {
|
|
1705
|
+
...baseInputs,
|
|
1706
|
+
// No event - native form submit handles it via form's onNativeSubmit
|
|
1707
|
+
// Set type="submit" to trigger native form submission
|
|
1708
|
+
props: { ...fieldDef.props, type: 'submit' },
|
|
1709
|
+
// Evaluate the signal inside the computed - component receives plain boolean
|
|
1710
|
+
disabled: disabledSignal(),
|
|
1711
|
+
};
|
|
1712
|
+
if (fieldDef.hidden !== undefined) {
|
|
1713
|
+
inputs['hidden'] = fieldDef.hidden;
|
|
1714
|
+
}
|
|
1715
|
+
return inputs;
|
|
1716
|
+
});
|
|
1717
|
+
}
|
|
1718
|
+
/**
|
|
1719
|
+
* Mapper for next page button - preconfigures NextPageEvent
|
|
1720
|
+
*
|
|
1721
|
+
* Disabled state is resolved using the button-logic-resolver which considers:
|
|
1722
|
+
* 1. Explicit `disabled: true` on the field definition
|
|
1723
|
+
* 2. Field-level `logic` array (if present, overrides form-level defaults)
|
|
1724
|
+
* 3. Form-level `options.nextButton` defaults (disableWhenPageInvalid, disableWhileSubmitting)
|
|
1725
|
+
*
|
|
1726
|
+
* @param fieldDef The next button field definition
|
|
1727
|
+
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1728
|
+
*/
|
|
1729
|
+
function nextButtonFieldMapper(fieldDef) {
|
|
1730
|
+
// Inject field signal context to access form state and options
|
|
1731
|
+
const fieldSignalContext = inject(FIELD_SIGNAL_CONTEXT);
|
|
1732
|
+
// Build base inputs (static, from field definition)
|
|
1733
|
+
const baseInputs = buildBaseInputs(fieldDef);
|
|
1734
|
+
// Use button-logic-resolver to compute disabled state
|
|
1735
|
+
const fieldWithLogic = fieldDef;
|
|
1736
|
+
const disabledSignal = resolveNextButtonDisabled({
|
|
1737
|
+
form: fieldSignalContext.form,
|
|
1738
|
+
formOptions: fieldSignalContext.formOptions,
|
|
1739
|
+
fieldLogic: fieldWithLogic.logic,
|
|
1740
|
+
explicitlyDisabled: fieldDef.disabled,
|
|
1741
|
+
currentPageValid: fieldSignalContext.currentPageValid,
|
|
1742
|
+
});
|
|
1743
|
+
// Return computed signal - evaluates disabledSignal inside for reactivity
|
|
1744
|
+
return computed(() => {
|
|
1745
|
+
const inputs = {
|
|
1746
|
+
...baseInputs,
|
|
1747
|
+
event: NextPageEvent,
|
|
1748
|
+
// Evaluate the signal inside the computed - component receives plain boolean
|
|
1749
|
+
disabled: disabledSignal(),
|
|
1750
|
+
};
|
|
1751
|
+
if (fieldDef.hidden !== undefined) {
|
|
1752
|
+
inputs['hidden'] = fieldDef.hidden;
|
|
1753
|
+
}
|
|
1754
|
+
return inputs;
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1757
|
+
/**
|
|
1758
|
+
* Mapper for previous page button - preconfigures PreviousPageEvent
|
|
1759
|
+
* Note: Does not auto-disable based on validation. Users can explicitly disable if needed.
|
|
1760
|
+
*
|
|
1761
|
+
* @param fieldDef The previous button field definition
|
|
1762
|
+
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1763
|
+
*/
|
|
1764
|
+
function previousButtonFieldMapper(fieldDef) {
|
|
1765
|
+
// Build base inputs (static, from field definition)
|
|
1766
|
+
const baseInputs = buildBaseInputs(fieldDef);
|
|
1767
|
+
return computed(() => {
|
|
1768
|
+
const inputs = {
|
|
1769
|
+
...baseInputs,
|
|
1770
|
+
event: PreviousPageEvent,
|
|
1771
|
+
};
|
|
1772
|
+
// Add disabled binding only if explicitly set by user
|
|
1773
|
+
if (fieldDef.disabled !== undefined) {
|
|
1774
|
+
inputs['disabled'] = fieldDef.disabled;
|
|
1775
|
+
}
|
|
1776
|
+
if (fieldDef.hidden !== undefined) {
|
|
1777
|
+
inputs['hidden'] = fieldDef.hidden;
|
|
1778
|
+
}
|
|
1779
|
+
return inputs;
|
|
1780
|
+
});
|
|
1781
|
+
}
|
|
1782
|
+
/**
|
|
1783
|
+
* Mapper for add array item button - preconfigures AddArrayItemEvent with array context.
|
|
1784
|
+
*
|
|
1785
|
+
* Supports two modes:
|
|
1786
|
+
* 1. Inside array template: Uses ARRAY_CONTEXT to determine target array
|
|
1787
|
+
* 2. Outside array: Uses `arrayKey` property from field definition
|
|
1788
|
+
*
|
|
1789
|
+
* @param fieldDef The add array item button field definition
|
|
1790
|
+
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1791
|
+
*/
|
|
1792
|
+
function addArrayItemButtonFieldMapper(fieldDef) {
|
|
1793
|
+
// Try to get array context (available when inside an array)
|
|
1794
|
+
// Use optional injection so it doesn't fail when outside an array
|
|
1795
|
+
const arrayContext = inject(ARRAY_CONTEXT, { optional: true });
|
|
1796
|
+
// Determine the target array key
|
|
1797
|
+
// Priority: explicit arrayKey from fieldDef > arrayKey from context
|
|
1798
|
+
const targetArrayKey = fieldDef.arrayKey ?? arrayContext?.arrayKey;
|
|
1799
|
+
if (!targetArrayKey) {
|
|
1800
|
+
console.warn(`[Dynamic Forms] addArrayItem button "${fieldDef.key}" has no array context. ` +
|
|
1801
|
+
'Either place it inside an array field, or provide an explicit arrayKey property.');
|
|
1802
|
+
}
|
|
1803
|
+
// Build base inputs (static, from field definition)
|
|
1804
|
+
const baseInputs = buildBaseInputs(fieldDef);
|
|
1805
|
+
// Set default eventArgs for AddArrayItemEvent (arrayKey)
|
|
1806
|
+
// User can override by providing eventArgs in field definition
|
|
1807
|
+
const defaultEventArgs = ['$arrayKey'];
|
|
1808
|
+
const eventArgs = 'eventArgs' in fieldDef && fieldDef.eventArgs !== undefined ? fieldDef.eventArgs : defaultEventArgs;
|
|
1809
|
+
return computed(() => {
|
|
1810
|
+
// Read signal value if index is a signal (supports differential updates)
|
|
1811
|
+
const getIndex = () => {
|
|
1812
|
+
if (!arrayContext)
|
|
1813
|
+
return -1;
|
|
1814
|
+
return isSignal(arrayContext.index) ? arrayContext.index() : arrayContext.index;
|
|
1815
|
+
};
|
|
1816
|
+
const inputs = {
|
|
1817
|
+
...baseInputs,
|
|
1818
|
+
event: AddArrayItemEvent,
|
|
1819
|
+
eventArgs,
|
|
1820
|
+
eventContext: {
|
|
1821
|
+
key: fieldDef.key,
|
|
1822
|
+
index: getIndex(),
|
|
1823
|
+
arrayKey: targetArrayKey ?? '',
|
|
1824
|
+
formValue: arrayContext?.formValue ?? {},
|
|
1825
|
+
},
|
|
1826
|
+
};
|
|
1827
|
+
// Add disabled binding only if explicitly set by user
|
|
1828
|
+
if (fieldDef.disabled !== undefined) {
|
|
1829
|
+
inputs['disabled'] = fieldDef.disabled;
|
|
1830
|
+
}
|
|
1831
|
+
if (fieldDef.hidden !== undefined) {
|
|
1832
|
+
inputs['hidden'] = fieldDef.hidden;
|
|
1833
|
+
}
|
|
1834
|
+
return inputs;
|
|
1835
|
+
});
|
|
1836
|
+
}
|
|
1837
|
+
/**
|
|
1838
|
+
* Mapper for remove array item button - preconfigures RemoveArrayItemEvent with array context.
|
|
1839
|
+
*
|
|
1840
|
+
* Supports two modes:
|
|
1841
|
+
* 1. Inside array template: Uses ARRAY_CONTEXT to determine target array and removes item at current index
|
|
1842
|
+
* 2. Outside array: Uses `arrayKey` property from field definition, removes last item by default
|
|
1843
|
+
*
|
|
1844
|
+
* @param fieldDef The remove array item button field definition
|
|
1845
|
+
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1846
|
+
*/
|
|
1847
|
+
function removeArrayItemButtonFieldMapper(fieldDef) {
|
|
1848
|
+
// Try to get array context (available when inside an array)
|
|
1849
|
+
// Use optional injection so it doesn't fail when outside an array
|
|
1850
|
+
const arrayContext = inject(ARRAY_CONTEXT, { optional: true });
|
|
1851
|
+
// Determine the target array key
|
|
1852
|
+
// Priority: explicit arrayKey from fieldDef > arrayKey from context
|
|
1853
|
+
const targetArrayKey = fieldDef.arrayKey ?? arrayContext?.arrayKey;
|
|
1854
|
+
if (!targetArrayKey) {
|
|
1855
|
+
console.warn(`[Dynamic Forms] removeArrayItem button "${fieldDef.key}" has no array context. ` +
|
|
1856
|
+
'Either place it inside an array field, or provide an explicit arrayKey property.');
|
|
1857
|
+
}
|
|
1858
|
+
// Build base inputs (static, from field definition)
|
|
1859
|
+
const baseInputs = buildBaseInputs(fieldDef);
|
|
1860
|
+
// Set default eventArgs for RemoveArrayItemEvent (arrayKey, index if inside array)
|
|
1861
|
+
// When outside array, only pass arrayKey (removes last by default)
|
|
1862
|
+
// User can override by providing eventArgs in field definition
|
|
1863
|
+
const defaultEventArgs = arrayContext ? ['$arrayKey', '$index'] : ['$arrayKey'];
|
|
1864
|
+
const eventArgs = 'eventArgs' in fieldDef && fieldDef.eventArgs !== undefined ? fieldDef.eventArgs : defaultEventArgs;
|
|
1865
|
+
return computed(() => {
|
|
1866
|
+
// Read signal value if index is a signal (supports differential updates)
|
|
1867
|
+
const getIndex = () => {
|
|
1868
|
+
if (!arrayContext)
|
|
1869
|
+
return -1; // -1 means remove last (no specific index)
|
|
1870
|
+
return isSignal(arrayContext.index) ? arrayContext.index() : arrayContext.index;
|
|
1871
|
+
};
|
|
1872
|
+
const inputs = {
|
|
1873
|
+
...baseInputs,
|
|
1874
|
+
event: RemoveArrayItemEvent,
|
|
1875
|
+
eventArgs,
|
|
1876
|
+
eventContext: {
|
|
1877
|
+
key: fieldDef.key,
|
|
1878
|
+
index: getIndex(),
|
|
1879
|
+
arrayKey: targetArrayKey ?? '',
|
|
1880
|
+
formValue: arrayContext?.formValue ?? {},
|
|
1881
|
+
},
|
|
1882
|
+
};
|
|
1883
|
+
// Add disabled binding only if explicitly set by user
|
|
1884
|
+
if (fieldDef.disabled !== undefined) {
|
|
1885
|
+
inputs['disabled'] = fieldDef.disabled;
|
|
1886
|
+
}
|
|
1887
|
+
if (fieldDef.hidden !== undefined) {
|
|
1888
|
+
inputs['hidden'] = fieldDef.hidden;
|
|
1889
|
+
}
|
|
1890
|
+
return inputs;
|
|
1891
|
+
});
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
/**
|
|
1895
|
+
* Ionic field type definitions
|
|
1896
|
+
* Follows the FieldTypeDefinition interface for proper registry integration
|
|
1897
|
+
*/
|
|
1898
|
+
const IONIC_FIELD_TYPES = [
|
|
1899
|
+
{
|
|
1900
|
+
name: IonicField.Input,
|
|
1901
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicInput_component; }),
|
|
1902
|
+
mapper: valueFieldMapper,
|
|
1903
|
+
},
|
|
1904
|
+
{
|
|
1905
|
+
name: IonicField.Select,
|
|
1906
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicSelect_component; }),
|
|
1907
|
+
mapper: optionsFieldMapper,
|
|
1908
|
+
},
|
|
1909
|
+
{
|
|
1910
|
+
name: IonicField.Checkbox,
|
|
1911
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicCheckbox_component; }),
|
|
1912
|
+
mapper: checkboxFieldMapper,
|
|
1913
|
+
},
|
|
1914
|
+
{
|
|
1915
|
+
name: IonicField.Button,
|
|
1916
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1917
|
+
mapper: buttonFieldMapper,
|
|
1918
|
+
valueHandling: 'exclude',
|
|
1919
|
+
},
|
|
1920
|
+
{
|
|
1921
|
+
name: IonicField.Submit,
|
|
1922
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1923
|
+
mapper: submitButtonFieldMapper,
|
|
1924
|
+
valueHandling: 'exclude',
|
|
1925
|
+
},
|
|
1926
|
+
{
|
|
1927
|
+
name: IonicField.Next,
|
|
1928
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1929
|
+
mapper: nextButtonFieldMapper,
|
|
1930
|
+
valueHandling: 'exclude',
|
|
1931
|
+
},
|
|
1932
|
+
{
|
|
1933
|
+
name: IonicField.Previous,
|
|
1934
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1935
|
+
mapper: previousButtonFieldMapper,
|
|
1936
|
+
valueHandling: 'exclude',
|
|
1937
|
+
},
|
|
1938
|
+
{
|
|
1939
|
+
name: IonicField.AddArrayItem,
|
|
1940
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1941
|
+
mapper: addArrayItemButtonFieldMapper,
|
|
1942
|
+
valueHandling: 'exclude',
|
|
1943
|
+
},
|
|
1944
|
+
{
|
|
1945
|
+
name: IonicField.RemoveArrayItem,
|
|
1946
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1947
|
+
mapper: removeArrayItemButtonFieldMapper,
|
|
1948
|
+
valueHandling: 'exclude',
|
|
1949
|
+
},
|
|
1950
|
+
{
|
|
1951
|
+
name: IonicField.Textarea,
|
|
1952
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicTextarea_component; }),
|
|
1953
|
+
mapper: valueFieldMapper,
|
|
1954
|
+
},
|
|
1955
|
+
{
|
|
1956
|
+
name: IonicField.Radio,
|
|
1957
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicRadio_component; }),
|
|
1958
|
+
mapper: optionsFieldMapper,
|
|
1959
|
+
},
|
|
1960
|
+
{
|
|
1961
|
+
name: IonicField.MultiCheckbox,
|
|
1962
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicMultiCheckbox_component; }),
|
|
1963
|
+
mapper: optionsFieldMapper,
|
|
1964
|
+
},
|
|
1965
|
+
{
|
|
1966
|
+
name: IonicField.Datepicker,
|
|
1967
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicDatepicker_component; }),
|
|
1968
|
+
mapper: datepickerFieldMapper,
|
|
1969
|
+
},
|
|
1970
|
+
{
|
|
1971
|
+
name: IonicField.Slider,
|
|
1972
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicSlider_component; }),
|
|
1973
|
+
mapper: valueFieldMapper,
|
|
1974
|
+
},
|
|
1975
|
+
{
|
|
1976
|
+
name: IonicField.Toggle,
|
|
1977
|
+
loadComponent: () => Promise.resolve().then(function () { return ionicToggle_component; }),
|
|
1978
|
+
mapper: checkboxFieldMapper,
|
|
1979
|
+
},
|
|
1980
|
+
];
|
|
1981
|
+
|
|
1982
|
+
/**
|
|
1983
|
+
* Module augmentation for @ng-forge/dynamic-form
|
|
1984
|
+
* This file augments the FieldRegistryLeaves interface to include
|
|
1985
|
+
* all Ionic field types provided by this library.
|
|
1986
|
+
*/
|
|
1987
|
+
|
|
1988
|
+
/**
|
|
1989
|
+
* Configure dynamic forms with Ionic field types.
|
|
1990
|
+
* Provides all Ionic field types for use with provideDynamicForm.
|
|
1991
|
+
*
|
|
1992
|
+
* @param config - Optional global configuration for Ionic form fields
|
|
1993
|
+
*
|
|
1994
|
+
* @example
|
|
1995
|
+
* ```typescript
|
|
1996
|
+
* // Application-level setup
|
|
1997
|
+
* import { ApplicationConfig } from '@angular/core';
|
|
1998
|
+
* import { provideDynamicForm } from '@ng-forge/dynamic-form';
|
|
1999
|
+
* import { withIonicFields } from '@ng-forge/dynamic-form-ionic';
|
|
2000
|
+
*
|
|
2001
|
+
* export const appConfig: ApplicationConfig = {
|
|
2002
|
+
* providers: [
|
|
2003
|
+
* provideDynamicForm(...withIonicFields())
|
|
2004
|
+
* ]
|
|
2005
|
+
* };
|
|
2006
|
+
* ```
|
|
2007
|
+
*
|
|
2008
|
+
* @example
|
|
2009
|
+
* ```typescript
|
|
2010
|
+
* // With global configuration
|
|
2011
|
+
* export const appConfig: ApplicationConfig = {
|
|
2012
|
+
* providers: [
|
|
2013
|
+
* provideDynamicForm(
|
|
2014
|
+
* ...withIonicFields({
|
|
2015
|
+
* fill: 'outline',
|
|
2016
|
+
* labelPlacement: 'floating'
|
|
2017
|
+
* })
|
|
2018
|
+
* )
|
|
2019
|
+
* ]
|
|
2020
|
+
* };
|
|
2021
|
+
* ```
|
|
2022
|
+
*
|
|
2023
|
+
* @returns Array of field type definitions for Ionic components
|
|
2024
|
+
*/
|
|
2025
|
+
function withIonicFields(config) {
|
|
2026
|
+
const fields = IONIC_FIELD_TYPES;
|
|
2027
|
+
if (config) {
|
|
2028
|
+
fields.__configProviders = [
|
|
2029
|
+
{
|
|
2030
|
+
provide: IONIC_CONFIG,
|
|
2031
|
+
useValue: config,
|
|
2032
|
+
},
|
|
2033
|
+
];
|
|
2034
|
+
}
|
|
2035
|
+
return fields;
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
// Field fields
|
|
2039
|
+
|
|
2040
|
+
/**
|
|
2041
|
+
* Generated bundle index. Do not edit.
|
|
2042
|
+
*/
|
|
2043
|
+
|
|
2044
|
+
export { IONIC_CONFIG, IONIC_FIELD_TYPES, IonicButtonFieldComponent, IonicCheckboxFieldComponent, IonicDatepickerFieldComponent, IonicField, IonicInputFieldComponent, IonicMultiCheckboxFieldComponent, IonicRadioFieldComponent, IonicSelectFieldComponent, IonicSliderFieldComponent, IonicTextareaFieldComponent, IonicToggleFieldComponent, withIonicFields };
|
|
2045
|
+
//# sourceMappingURL=ng-forge-dynamic-forms-ionic.mjs.map
|