@ng-forge/dynamic-forms-ionic 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, input, computed, ChangeDetectionStrategy, Component, signal, InjectionToken, linkedSignal, model, isSignal } from '@angular/core';
2
+ import { inject, input, computed, ChangeDetectionStrategy, Component, ElementRef, signal, InjectionToken, linkedSignal, model, isSignal } from '@angular/core';
3
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
4
  import { EventBus, ARRAY_CONTEXT, resolveTokens, DynamicTextPipe, buildBaseInputs, FIELD_SIGNAL_CONTEXT, resolveSubmitButtonDisabled, resolveNextButtonDisabled, NextPageEvent, PreviousPageEvent, DynamicFormLogger, AddArrayItemEvent, RemoveArrayItemEvent } from '@ng-forge/dynamic-forms';
5
5
  import { AsyncPipe } from '@angular/common';
6
- import { Field } from '@angular/forms/signals';
7
- import { createResolvedErrorsSignal, shouldShowErrors, isEqual, ValueInArrayPipe, valueFieldMapper, optionsFieldMapper, checkboxFieldMapper, datepickerFieldMapper } from '@ng-forge/dynamic-forms/integration';
6
+ import { FormField } from '@angular/forms/signals';
7
+ import { createResolvedErrorsSignal, shouldShowErrors, setupMetaTracking, isEqual, ValueInArrayPipe, valueFieldMapper, optionsFieldMapper, checkboxFieldMapper, datepickerFieldMapper } from '@ng-forge/dynamic-forms/integration';
8
8
  import { format } from 'date-fns';
9
9
  import { explicitEffect } from 'ngxtension/explicit-effect';
10
10
 
@@ -64,9 +64,12 @@ class IonicButtonFieldComponent {
64
64
  this.eventBus.dispatch(event);
65
65
  }
66
66
  }
67
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicButtonFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
68
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", 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: `
67
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicButtonFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
68
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.8", type: IonicButtonFieldComponent, isStandalone: true, selector: "df-ion-button", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, event: { classPropertyName: "event", publicName: "event", isSignal: true, isRequired: false, transformFunction: null }, eventArgs: { classPropertyName: "eventArgs", publicName: "eventArgs", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, eventContext: { classPropertyName: "eventContext", publicName: "eventContext", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "class": "className()", "attr.data-testid": "key()" } }, ngImport: i0, template: `
69
+ @let buttonId = key() + '-button';
70
+
69
71
  <ion-button
72
+ [id]="buttonId"
70
73
  [type]="buttonType()"
71
74
  [expand]="props()?.expand"
72
75
  [fill]="props()?.fill || 'solid'"
@@ -74,7 +77,6 @@ class IonicButtonFieldComponent {
74
77
  [size]="props()?.size"
75
78
  [color]="props()?.color || 'primary'"
76
79
  [strong]="props()?.strong"
77
- [class]="className() || ''"
78
80
  [disabled]="disabled()"
79
81
  [attr.data-testid]="buttonTestId()"
80
82
  (click)="onClick()"
@@ -83,17 +85,21 @@ class IonicButtonFieldComponent {
83
85
  </ion-button>
84
86
  `, 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 });
85
87
  }
86
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicButtonFieldComponent, decorators: [{
88
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicButtonFieldComponent, decorators: [{
87
89
  type: Component,
88
90
  args: [{
89
- selector: 'df-ionic-button',
91
+ selector: 'df-ion-button',
90
92
  imports: [IonButton, DynamicTextPipe, AsyncPipe],
91
93
  host: {
92
94
  '[id]': '`${key()}`',
95
+ '[class]': 'className()',
93
96
  '[attr.data-testid]': 'key()',
94
97
  },
95
98
  template: `
99
+ @let buttonId = key() + '-button';
100
+
96
101
  <ion-button
102
+ [id]="buttonId"
97
103
  [type]="buttonType()"
98
104
  [expand]="props()?.expand"
99
105
  [fill]="props()?.fill || 'solid'"
@@ -101,7 +107,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
101
107
  [size]="props()?.size"
102
108
  [color]="props()?.color || 'primary'"
103
109
  [strong]="props()?.strong"
104
- [class]="className() || ''"
105
110
  [disabled]="disabled()"
106
111
  [attr.data-testid]="buttonTestId()"
107
112
  (click)="onClick()"
@@ -121,6 +126,7 @@ var ionicButton_component = /*#__PURE__*/Object.freeze({
121
126
  // Public API - component
122
127
 
123
128
  class IonicCheckboxFieldComponent {
129
+ elementRef = inject((ElementRef));
124
130
  field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
125
131
  key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
126
132
  // Properties
@@ -129,11 +135,18 @@ class IonicCheckboxFieldComponent {
129
135
  className = input('', ...(ngDevMode ? [{ debugName: "className" }] : []));
130
136
  tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : []));
131
137
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : []));
138
+ meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : []));
132
139
  validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : []));
133
140
  defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : []));
134
141
  resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
135
142
  showErrors = shouldShowErrors(this.field);
136
143
  errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : []));
144
+ constructor() {
145
+ // Shadow DOM - apply meta to ion-checkbox element
146
+ setupMetaTracking(this.elementRef, this.meta, {
147
+ selector: 'ion-checkbox',
148
+ });
149
+ }
137
150
  // ─────────────────────────────────────────────────────────────────────────────
138
151
  // Accessibility
139
152
  // ─────────────────────────────────────────────────────────────────────────────
@@ -148,12 +161,14 @@ class IonicCheckboxFieldComponent {
148
161
  isRequired = computed(() => {
149
162
  return this.field()().required?.() === true;
150
163
  }, ...(ngDevMode ? [{ debugName: "isRequired" }] : []));
151
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
152
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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: `
164
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
165
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: IonicCheckboxFieldComponent, isStandalone: true, selector: "df-ion-checkbox", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
153
166
  @let f = field();
167
+ @let checkboxId = key() + '-checkbox';
154
168
 
155
169
  <ion-checkbox
156
- [field]="f"
170
+ [id]="checkboxId"
171
+ [formField]="f"
157
172
  [labelPlacement]="props()?.labelPlacement ?? 'end'"
158
173
  [justify]="props()?.justify"
159
174
  [color]="props()?.color ?? 'primary'"
@@ -168,15 +183,17 @@ class IonicCheckboxFieldComponent {
168
183
  @for (error of errorsToDisplay(); track error.kind; let i = $index) {
169
184
  <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
170
185
  }
171
- `, 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 });
186
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
172
187
  }
173
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicCheckboxFieldComponent, decorators: [{
188
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicCheckboxFieldComponent, decorators: [{
174
189
  type: Component,
175
- args: [{ selector: 'df-ionic-checkbox', imports: [IonCheckbox, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
190
+ args: [{ selector: 'df-ion-checkbox', imports: [IonCheckbox, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
176
191
  @let f = field();
192
+ @let checkboxId = key() + '-checkbox';
177
193
 
178
194
  <ion-checkbox
179
- [field]="f"
195
+ [id]="checkboxId"
196
+ [formField]="f"
180
197
  [labelPlacement]="props()?.labelPlacement ?? 'end'"
181
198
  [justify]="props()?.justify"
182
199
  [color]="props()?.color ?? 'primary'"
@@ -196,8 +213,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
196
213
  '[id]': '`${key()}`',
197
214
  '[attr.data-testid]': 'key()',
198
215
  '[attr.hidden]': 'field()().hidden() || null',
199
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}:host([hidden]){display:none!important}\n"] }]
200
- }], 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 }] }] } });
216
+ }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
217
+ }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
201
218
 
202
219
  var ionicCheckbox_component = /*#__PURE__*/Object.freeze({
203
220
  __proto__: null,
@@ -205,6 +222,7 @@ var ionicCheckbox_component = /*#__PURE__*/Object.freeze({
205
222
  });
206
223
 
207
224
  class IonicDatepickerFieldComponent {
225
+ elementRef = inject((ElementRef));
208
226
  field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
209
227
  key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
210
228
  label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
@@ -215,12 +233,19 @@ class IonicDatepickerFieldComponent {
215
233
  maxDate = input(null, ...(ngDevMode ? [{ debugName: "maxDate" }] : []));
216
234
  startAt = input(null, ...(ngDevMode ? [{ debugName: "startAt" }] : []));
217
235
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : []));
236
+ meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : []));
218
237
  validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : []));
219
238
  defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : []));
220
239
  resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
221
240
  showErrors = shouldShowErrors(this.field);
222
241
  errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : []));
223
242
  isModalOpen = signal(false, ...(ngDevMode ? [{ debugName: "isModalOpen" }] : []));
243
+ constructor() {
244
+ // Shadow DOM - apply meta to ion-input element
245
+ setupMetaTracking(this.elementRef, this.meta, {
246
+ selector: 'ion-input',
247
+ });
248
+ }
224
249
  // ─────────────────────────────────────────────────────────────────────────────
225
250
  // Accessibility
226
251
  // ─────────────────────────────────────────────────────────────────────────────
@@ -279,11 +304,15 @@ class IonicDatepickerFieldComponent {
279
304
  return format(date, 'MMM d, yyyy');
280
305
  }
281
306
  }
282
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicDatepickerFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
283
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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: `
307
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicDatepickerFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
308
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: IonicDatepickerFieldComponent, isStandalone: true, selector: "df-ion-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 }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
284
309
  @let f = field(); @let dateValue = f().value();
310
+ @let ariaInvalid = isAriaInvalid();
311
+ @let ariaRequired = isRequired() || null;
312
+ @let inputId = key() + '-input';
285
313
 
286
314
  <ion-input
315
+ [id]="inputId"
287
316
  [label]="(label() | dynamicText | async) ?? undefined"
288
317
  [labelPlacement]="'stacked'"
289
318
  [placeholder]="(placeholder() | dynamicText | async) ?? ''"
@@ -292,18 +321,13 @@ class IonicDatepickerFieldComponent {
292
321
  [readonly]="true"
293
322
  [fill]="'outline'"
294
323
  [attr.tabindex]="tabIndex()"
295
- [attr.aria-invalid]="isAriaInvalid()"
296
- [attr.aria-required]="isRequired() || null"
297
- [class.ion-invalid]="f().invalid()"
298
- [class.ion-touched]="f().touched()"
324
+ [attr.aria-invalid]="ariaInvalid"
325
+ [attr.aria-required]="ariaRequired"
299
326
  (click)="!f().disabled() && openModal()"
300
- >
301
- <div slot="error">
302
- @for (error of errorsToDisplay(); track error.kind; let i = $index) {
303
- <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
304
- }
305
- </div>
306
- </ion-input>
327
+ />
328
+ @for (error of errorsToDisplay(); track error.kind; let i = $index) {
329
+ <ion-note color="danger" class="df-ion-error" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
330
+ }
307
331
 
308
332
  <ion-modal [isOpen]="isModalOpen()" (didDismiss)="closeModal()">
309
333
  <ng-template>
@@ -334,11 +358,11 @@ class IonicDatepickerFieldComponent {
334
358
  </ion-content>
335
359
  </ng-template>
336
360
  </ion-modal>
337
- `, 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 });
361
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", "ion-input{cursor:pointer}:host([hidden]){display:none!important}\n"], 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 });
338
362
  }
339
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicDatepickerFieldComponent, decorators: [{
363
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicDatepickerFieldComponent, decorators: [{
340
364
  type: Component,
341
- args: [{ selector: 'df-ionic-datepicker', imports: [
365
+ args: [{ selector: 'df-ion-datepicker', imports: [
342
366
  IonInput,
343
367
  IonModal,
344
368
  IonDatetime,
@@ -353,8 +377,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
353
377
  AsyncPipe,
354
378
  ], template: `
355
379
  @let f = field(); @let dateValue = f().value();
380
+ @let ariaInvalid = isAriaInvalid();
381
+ @let ariaRequired = isRequired() || null;
382
+ @let inputId = key() + '-input';
356
383
 
357
384
  <ion-input
385
+ [id]="inputId"
358
386
  [label]="(label() | dynamicText | async) ?? undefined"
359
387
  [labelPlacement]="'stacked'"
360
388
  [placeholder]="(placeholder() | dynamicText | async) ?? ''"
@@ -363,18 +391,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
363
391
  [readonly]="true"
364
392
  [fill]="'outline'"
365
393
  [attr.tabindex]="tabIndex()"
366
- [attr.aria-invalid]="isAriaInvalid()"
367
- [attr.aria-required]="isRequired() || null"
368
- [class.ion-invalid]="f().invalid()"
369
- [class.ion-touched]="f().touched()"
394
+ [attr.aria-invalid]="ariaInvalid"
395
+ [attr.aria-required]="ariaRequired"
370
396
  (click)="!f().disabled() && openModal()"
371
- >
372
- <div slot="error">
373
- @for (error of errorsToDisplay(); track error.kind; let i = $index) {
374
- <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
375
- }
376
- </div>
377
- </ion-input>
397
+ />
398
+ @for (error of errorsToDisplay(); track error.kind; let i = $index) {
399
+ <ion-note color="danger" class="df-ion-error" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
400
+ }
378
401
 
379
402
  <ion-modal [isOpen]="isModalOpen()" (didDismiss)="closeModal()">
380
403
  <ng-template>
@@ -410,8 +433,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
410
433
  '[attr.data-testid]': 'key()',
411
434
  '[class]': 'className()',
412
435
  '[attr.hidden]': 'field()().hidden() || null',
413
- }, styles: ["ion-input{cursor:pointer}:host([hidden]){display:none!important}\n"] }]
414
- }], 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 }] }] } });
436
+ }, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", "ion-input{cursor:pointer}:host([hidden]){display:none!important}\n"] }]
437
+ }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], startAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAt", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
415
438
 
416
439
  var ionicDatepicker_component = /*#__PURE__*/Object.freeze({
417
440
  __proto__: null,
@@ -442,6 +465,7 @@ var ionicDatepicker_component = /*#__PURE__*/Object.freeze({
442
465
  const IONIC_CONFIG = new InjectionToken('IONIC_CONFIG');
443
466
 
444
467
  class IonicInputFieldComponent {
468
+ elementRef = inject((ElementRef));
445
469
  ionicConfig = inject(IONIC_CONFIG, { optional: true });
446
470
  field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
447
471
  key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
@@ -450,6 +474,7 @@ class IonicInputFieldComponent {
450
474
  className = input('', ...(ngDevMode ? [{ debugName: "className" }] : []));
451
475
  tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : []));
452
476
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : []));
477
+ meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : []));
453
478
  validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : []));
454
479
  defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : []));
455
480
  effectiveFill = computed(() => this.props()?.fill ?? this.ionicConfig?.fill ?? 'solid', ...(ngDevMode ? [{ debugName: "effectiveFill" }] : []));
@@ -459,6 +484,12 @@ class IonicInputFieldComponent {
459
484
  resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
460
485
  showErrors = shouldShowErrors(this.field);
461
486
  errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : []));
487
+ constructor() {
488
+ // Shadow DOM - apply meta to ion-input element
489
+ setupMetaTracking(this.elementRef, this.meta, {
490
+ selector: 'ion-input',
491
+ });
492
+ }
462
493
  // ─────────────────────────────────────────────────────────────────────────────
463
494
  // Accessibility
464
495
  // ─────────────────────────────────────────────────────────────────────────────
@@ -473,15 +504,17 @@ class IonicInputFieldComponent {
473
504
  isRequired = computed(() => {
474
505
  return this.field()().required?.() === true;
475
506
  }, ...(ngDevMode ? [{ debugName: "isRequired" }] : []));
476
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicInputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
477
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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: `
507
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicInputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
508
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: IonicInputFieldComponent, isStandalone: true, selector: "df-ion-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 }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
478
509
  @let f = field();
479
510
  @let ariaInvalid = isAriaInvalid();
480
511
  @let ariaRequired = isRequired() || null;
512
+ @let inputId = key() + '-input';
481
513
 
482
514
  <ion-input
515
+ [id]="inputId"
483
516
  [type]="props()?.type ?? 'text'"
484
- [field]="f"
517
+ [formField]="f"
485
518
  [label]="(label() | dynamicText | async) ?? undefined"
486
519
  [labelPlacement]="effectiveLabelPlacement()"
487
520
  [placeholder]="(placeholder() | dynamicText | async) ?? ''"
@@ -492,31 +525,27 @@ class IonicInputFieldComponent {
492
525
  [shape]="effectiveShape()"
493
526
  [readonly]="f().readonly()"
494
527
  [helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
495
- [errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
496
528
  [attr.tabindex]="tabIndex()"
497
529
  [attr.aria-invalid]="ariaInvalid"
498
530
  [attr.aria-required]="ariaRequired"
499
- [class.ion-invalid]="f().invalid()"
500
- [class.ion-touched]="f().touched()"
501
- >
502
- <div slot="error">
503
- @for (error of errorsToDisplay(); track error.kind; let i = $index) {
504
- <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
505
- }
506
- </div>
507
- </ion-input>
508
- `, 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 });
531
+ />
532
+ @for (error of errorsToDisplay(); track error.kind; let i = $index) {
533
+ <ion-note color="danger" class="df-ion-error" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
534
+ }
535
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
509
536
  }
510
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicInputFieldComponent, decorators: [{
537
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicInputFieldComponent, decorators: [{
511
538
  type: Component,
512
- args: [{ selector: 'df-ionic-input', imports: [IonInput, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
539
+ args: [{ selector: 'df-ion-input', imports: [IonInput, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
513
540
  @let f = field();
514
541
  @let ariaInvalid = isAriaInvalid();
515
542
  @let ariaRequired = isRequired() || null;
543
+ @let inputId = key() + '-input';
516
544
 
517
545
  <ion-input
546
+ [id]="inputId"
518
547
  [type]="props()?.type ?? 'text'"
519
- [field]="f"
548
+ [formField]="f"
520
549
  [label]="(label() | dynamicText | async) ?? undefined"
521
550
  [labelPlacement]="effectiveLabelPlacement()"
522
551
  [placeholder]="(placeholder() | dynamicText | async) ?? ''"
@@ -527,26 +556,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
527
556
  [shape]="effectiveShape()"
528
557
  [readonly]="f().readonly()"
529
558
  [helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
530
- [errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
531
559
  [attr.tabindex]="tabIndex()"
532
560
  [attr.aria-invalid]="ariaInvalid"
533
561
  [attr.aria-required]="ariaRequired"
534
- [class.ion-invalid]="f().invalid()"
535
- [class.ion-touched]="f().touched()"
536
- >
537
- <div slot="error">
538
- @for (error of errorsToDisplay(); track error.kind; let i = $index) {
539
- <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
540
- }
541
- </div>
542
- </ion-input>
562
+ />
563
+ @for (error of errorsToDisplay(); track error.kind; let i = $index) {
564
+ <ion-note color="danger" class="df-ion-error" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
565
+ }
543
566
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
544
567
  '[id]': '`${key()}`',
545
568
  '[attr.data-testid]': 'key()',
546
569
  '[class]': 'className()',
547
570
  '[attr.hidden]': 'field()().hidden() || null',
548
- }, styles: [":host([hidden]){display:none!important}\n"] }]
549
- }], 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 }] }] } });
571
+ }, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host([hidden]){display:none!important}\n"] }]
572
+ }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
550
573
 
551
574
  var ionicInput_component = /*#__PURE__*/Object.freeze({
552
575
  __proto__: null,
@@ -554,6 +577,7 @@ var ionicInput_component = /*#__PURE__*/Object.freeze({
554
577
  });
555
578
 
556
579
  class IonicMultiCheckboxFieldComponent {
580
+ elementRef = inject((ElementRef));
557
581
  field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
558
582
  key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
559
583
  label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
@@ -562,6 +586,7 @@ class IonicMultiCheckboxFieldComponent {
562
586
  tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : []));
563
587
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
564
588
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : []));
589
+ meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : []));
565
590
  validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : []));
566
591
  defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : []));
567
592
  resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
@@ -586,6 +611,11 @@ class IonicMultiCheckboxFieldComponent {
586
611
  return this.options().filter((option) => currentValues.includes(option.value));
587
612
  }, { ...(ngDevMode ? { debugName: "valueViewModel" } : {}), equal: isEqual });
588
613
  constructor() {
614
+ // Shadow DOM - apply meta to ion-checkbox elements, re-apply when options change
615
+ setupMetaTracking(this.elementRef, this.meta, {
616
+ selector: 'ion-checkbox',
617
+ dependents: [this.options],
618
+ });
589
619
  explicitEffect([this.valueViewModel], ([selectedOptions]) => {
590
620
  const selectedValues = selectedOptions.map((option) => option.value);
591
621
  if (!isEqual(selectedValues, this.field()().value())) {
@@ -611,14 +641,21 @@ class IonicMultiCheckboxFieldComponent {
611
641
  }
612
642
  });
613
643
  }
614
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicMultiCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
615
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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: `
644
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicMultiCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
645
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: IonicMultiCheckboxFieldComponent, isStandalone: true, selector: "df-ion-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 }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className() || \"\"", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, providers: [ValueInArrayPipe], ngImport: i0, template: `
616
646
  @let f = field();
617
647
  @if (label(); as label) {
618
648
  <div class="checkbox-group-label">{{ label | dynamicText | async }}</div>
619
649
  }
620
650
 
621
- <div class="checkbox-group" role="group" [attr.aria-invalid]="isAriaInvalid()" [attr.aria-required]="isRequired() || null">
651
+ <div
652
+ class="checkbox-group"
653
+ role="group"
654
+ [attr.aria-invalid]="isAriaInvalid()"
655
+ [attr.aria-required]="isRequired() || null"
656
+ [class.ion-invalid]="showErrors()"
657
+ [class.ion-touched]="field()().touched()"
658
+ >
622
659
  @for (option of options(); track option.value) {
623
660
  <ion-item lines="none">
624
661
  <ion-checkbox
@@ -638,17 +675,24 @@ class IonicMultiCheckboxFieldComponent {
638
675
  @for (error of errorsToDisplay(); track error.kind; let i = $index) {
639
676
  <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
640
677
  }
641
- `, 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 });
678
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}.checkbox-group-label{margin-bottom:8px;font-weight:500}.checkbox-group{display:flex;flex-direction:column;gap:4px}ion-item{--padding-start: 0;--inner-padding-end: 0}\n"], 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 });
642
679
  }
643
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicMultiCheckboxFieldComponent, decorators: [{
680
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicMultiCheckboxFieldComponent, decorators: [{
644
681
  type: Component,
645
- args: [{ selector: 'df-ionic-multi-checkbox', imports: [IonCheckbox, IonItem, IonNote, ValueInArrayPipe, DynamicTextPipe, AsyncPipe], template: `
682
+ args: [{ selector: 'df-ion-multi-checkbox', imports: [IonCheckbox, IonItem, IonNote, ValueInArrayPipe, DynamicTextPipe, AsyncPipe], template: `
646
683
  @let f = field();
647
684
  @if (label(); as label) {
648
685
  <div class="checkbox-group-label">{{ label | dynamicText | async }}</div>
649
686
  }
650
687
 
651
- <div class="checkbox-group" role="group" [attr.aria-invalid]="isAriaInvalid()" [attr.aria-required]="isRequired() || null">
688
+ <div
689
+ class="checkbox-group"
690
+ role="group"
691
+ [attr.aria-invalid]="isAriaInvalid()"
692
+ [attr.aria-required]="isRequired() || null"
693
+ [class.ion-invalid]="showErrors()"
694
+ [class.ion-touched]="field()().touched()"
695
+ >
652
696
  @for (option of options(); track option.value) {
653
697
  <ion-item lines="none">
654
698
  <ion-checkbox
@@ -673,8 +717,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
673
717
  '[id]': '`${key()}`',
674
718
  '[attr.data-testid]': 'key()',
675
719
  '[attr.hidden]': 'field()().hidden() || null',
676
- }, 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"] }]
677
- }], 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 }] }] } });
720
+ }, providers: [ValueInArrayPipe], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}.checkbox-group-label{margin-bottom:8px;font-weight:500}.checkbox-group{display:flex;flex-direction:column;gap:4px}ion-item{--padding-start: 0;--inner-padding-end: 0}\n"] }]
721
+ }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
678
722
 
679
723
  var ionicMultiCheckbox_component = /*#__PURE__*/Object.freeze({
680
724
  __proto__: null,
@@ -682,6 +726,7 @@ var ionicMultiCheckbox_component = /*#__PURE__*/Object.freeze({
682
726
  });
683
727
 
684
728
  class IonicRadioFieldComponent {
729
+ elementRef = inject((ElementRef));
685
730
  field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
686
731
  key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
687
732
  // Properties
@@ -691,12 +736,20 @@ class IonicRadioFieldComponent {
691
736
  tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : []));
692
737
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
693
738
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : []));
739
+ meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : []));
694
740
  validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : []));
695
741
  defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : []));
696
742
  resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
697
743
  showErrors = shouldShowErrors(this.field);
698
744
  errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : []));
699
745
  defaultCompare = Object.is;
746
+ constructor() {
747
+ // Shadow DOM - apply meta to ion-radio elements, re-apply when options change
748
+ setupMetaTracking(this.elementRef, this.meta, {
749
+ selector: 'ion-radio',
750
+ dependents: [this.options],
751
+ });
752
+ }
700
753
  // ─────────────────────────────────────────────────────────────────────────────
701
754
  // Accessibility
702
755
  // ─────────────────────────────────────────────────────────────────────────────
@@ -711,15 +764,17 @@ class IonicRadioFieldComponent {
711
764
  isRequired = computed(() => {
712
765
  return this.field()().required?.() === true;
713
766
  }, ...(ngDevMode ? [{ debugName: "isRequired" }] : []));
714
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicRadioFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
715
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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: `
767
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicRadioFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
768
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: IonicRadioFieldComponent, isStandalone: true, selector: "df-ion-radio", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
716
769
  @let f = field();
770
+ @let radioGroupId = key() + '-radio-group';
717
771
  @if (label(); as label) {
718
772
  <div class="radio-label">{{ label | dynamicText | async }}</div>
719
773
  }
720
774
 
721
775
  <ion-radio-group
722
- [field]="f"
776
+ [id]="radioGroupId"
777
+ [formField]="f"
723
778
  [compareWith]="props()?.compareWith || defaultCompare"
724
779
  [attr.aria-invalid]="isAriaInvalid()"
725
780
  [attr.aria-required]="isRequired() || null"
@@ -742,18 +797,20 @@ class IonicRadioFieldComponent {
742
797
  @for (error of errorsToDisplay(); track error.kind; let i = $index) {
743
798
  <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
744
799
  }
745
- `, 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 });
800
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}.radio-label{font-size:.875rem;font-weight:500;margin-bottom:.5rem;color:var(--ion-text-color)}\n"], dependencies: [{ kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
746
801
  }
747
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicRadioFieldComponent, decorators: [{
802
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicRadioFieldComponent, decorators: [{
748
803
  type: Component,
749
- args: [{ selector: 'df-ionic-radio', imports: [IonRadioGroup, IonRadio, IonItem, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
804
+ args: [{ selector: 'df-ion-radio', imports: [IonRadioGroup, IonRadio, IonItem, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
750
805
  @let f = field();
806
+ @let radioGroupId = key() + '-radio-group';
751
807
  @if (label(); as label) {
752
808
  <div class="radio-label">{{ label | dynamicText | async }}</div>
753
809
  }
754
810
 
755
811
  <ion-radio-group
756
- [field]="f"
812
+ [id]="radioGroupId"
813
+ [formField]="f"
757
814
  [compareWith]="props()?.compareWith || defaultCompare"
758
815
  [attr.aria-invalid]="isAriaInvalid()"
759
816
  [attr.aria-required]="isRequired() || null"
@@ -781,8 +838,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
781
838
  '[id]': '`${key()}`',
782
839
  '[attr.data-testid]': 'key()',
783
840
  '[attr.hidden]': 'field()().hidden() || null',
784
- }, 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"] }]
785
- }], 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 }] }] } });
841
+ }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}.radio-label{font-size:.875rem;font-weight:500;margin-bottom:.5rem;color:var(--ion-text-color)}\n"] }]
842
+ }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
786
843
 
787
844
  var ionicRadio_component = /*#__PURE__*/Object.freeze({
788
845
  __proto__: null,
@@ -790,6 +847,7 @@ var ionicRadio_component = /*#__PURE__*/Object.freeze({
790
847
  });
791
848
 
792
849
  class IonicSelectFieldComponent {
850
+ elementRef = inject((ElementRef));
793
851
  field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
794
852
  key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
795
853
  label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
@@ -798,8 +856,12 @@ class IonicSelectFieldComponent {
798
856
  tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : []));
799
857
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
800
858
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : []));
859
+ meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : []));
801
860
  validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : []));
802
861
  defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : []));
862
+ constructor() {
863
+ setupMetaTracking(this.elementRef, this.meta);
864
+ }
803
865
  resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
804
866
  showErrors = shouldShowErrors(this.field);
805
867
  errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : []));
@@ -818,12 +880,16 @@ class IonicSelectFieldComponent {
818
880
  isRequired = computed(() => {
819
881
  return this.field()().required?.() === true;
820
882
  }, ...(ngDevMode ? [{ debugName: "isRequired" }] : []));
821
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
822
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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: `
883
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
884
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: IonicSelectFieldComponent, isStandalone: true, selector: "df-ion-select", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
823
885
  @let f = field();
886
+ @let ariaInvalid = isAriaInvalid();
887
+ @let ariaRequired = isRequired() || null;
888
+ @let selectId = key() + '-select';
824
889
 
825
890
  <ion-select
826
- [field]="f"
891
+ [id]="selectId"
892
+ [formField]="f"
827
893
  [label]="(label() | dynamicText | async) ?? undefined"
828
894
  [labelPlacement]="props()?.labelPlacement ?? 'stacked'"
829
895
  [placeholder]="(placeholder() ?? props()?.placeholder | dynamicText | async) ?? ''"
@@ -837,31 +903,31 @@ class IonicSelectFieldComponent {
837
903
  [fill]="props()?.fill ?? 'outline'"
838
904
  [shape]="props()?.shape"
839
905
  [attr.tabindex]="tabIndex()"
840
- [attr.aria-invalid]="isAriaInvalid()"
841
- [attr.aria-required]="isRequired() || null"
842
- [class.ion-invalid]="f().invalid()"
843
- [class.ion-touched]="f().touched()"
906
+ [attr.aria-invalid]="ariaInvalid"
907
+ [attr.aria-required]="ariaRequired"
844
908
  >
845
909
  @for (option of options(); track option.value) {
846
910
  <ion-select-option [value]="option.value" [disabled]="option.disabled || false">
847
911
  {{ option.label | dynamicText | async }}
848
912
  </ion-select-option>
849
913
  }
850
- <div slot="error">
851
- @for (error of errorsToDisplay(); track error.kind; let i = $index) {
852
- <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
853
- }
854
- </div>
855
914
  </ion-select>
856
- `, 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 });
915
+ @for (error of errorsToDisplay(); track error.kind; let i = $index) {
916
+ <ion-note color="danger" class="df-ion-error" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
917
+ }
918
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
857
919
  }
858
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicSelectFieldComponent, decorators: [{
920
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicSelectFieldComponent, decorators: [{
859
921
  type: Component,
860
- args: [{ selector: 'df-ionic-select', imports: [IonSelect, IonSelectOption, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
922
+ args: [{ selector: 'df-ion-select', imports: [IonSelect, IonSelectOption, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
861
923
  @let f = field();
924
+ @let ariaInvalid = isAriaInvalid();
925
+ @let ariaRequired = isRequired() || null;
926
+ @let selectId = key() + '-select';
862
927
 
863
928
  <ion-select
864
- [field]="f"
929
+ [id]="selectId"
930
+ [formField]="f"
865
931
  [label]="(label() | dynamicText | async) ?? undefined"
866
932
  [labelPlacement]="props()?.labelPlacement ?? 'stacked'"
867
933
  [placeholder]="(placeholder() ?? props()?.placeholder | dynamicText | async) ?? ''"
@@ -875,29 +941,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
875
941
  [fill]="props()?.fill ?? 'outline'"
876
942
  [shape]="props()?.shape"
877
943
  [attr.tabindex]="tabIndex()"
878
- [attr.aria-invalid]="isAriaInvalid()"
879
- [attr.aria-required]="isRequired() || null"
880
- [class.ion-invalid]="f().invalid()"
881
- [class.ion-touched]="f().touched()"
944
+ [attr.aria-invalid]="ariaInvalid"
945
+ [attr.aria-required]="ariaRequired"
882
946
  >
883
947
  @for (option of options(); track option.value) {
884
948
  <ion-select-option [value]="option.value" [disabled]="option.disabled || false">
885
949
  {{ option.label | dynamicText | async }}
886
950
  </ion-select-option>
887
951
  }
888
- <div slot="error">
889
- @for (error of errorsToDisplay(); track error.kind; let i = $index) {
890
- <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
891
- }
892
- </div>
893
952
  </ion-select>
953
+ @for (error of errorsToDisplay(); track error.kind; let i = $index) {
954
+ <ion-note color="danger" class="df-ion-error" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
955
+ }
894
956
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
895
957
  '[id]': '`${key()}`',
896
958
  '[attr.data-testid]': 'key()',
897
959
  '[class]': 'className()',
898
960
  '[attr.hidden]': 'field()().hidden() || null',
899
- }, styles: [":host([hidden]){display:none!important}\n"] }]
900
- }], 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 }] }] } });
961
+ }, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host([hidden]){display:none!important}\n"] }]
962
+ }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
901
963
 
902
964
  var ionicSelect_component = /*#__PURE__*/Object.freeze({
903
965
  __proto__: null,
@@ -905,6 +967,7 @@ var ionicSelect_component = /*#__PURE__*/Object.freeze({
905
967
  });
906
968
 
907
969
  class IonicSliderFieldComponent {
970
+ elementRef = inject((ElementRef));
908
971
  field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
909
972
  key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
910
973
  label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
@@ -912,8 +975,12 @@ class IonicSliderFieldComponent {
912
975
  className = input('', ...(ngDevMode ? [{ debugName: "className" }] : []));
913
976
  tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : []));
914
977
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : []));
978
+ meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : []));
915
979
  validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : []));
916
980
  defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : []));
981
+ constructor() {
982
+ setupMetaTracking(this.elementRef, this.meta);
983
+ }
917
984
  resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
918
985
  showErrors = shouldShowErrors(this.field);
919
986
  errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : []));
@@ -932,12 +999,14 @@ class IonicSliderFieldComponent {
932
999
  isRequired = computed(() => {
933
1000
  return this.field()().required?.() === true;
934
1001
  }, ...(ngDevMode ? [{ debugName: "isRequired" }] : []));
935
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicSliderFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
936
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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: `
1002
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicSliderFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1003
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: IonicSliderFieldComponent, isStandalone: true, selector: "df-ion-slider", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
937
1004
  @let f = field();
1005
+ @let inputId = key() + '-input';
938
1006
 
939
1007
  <ion-range
940
- [field]="f"
1008
+ [id]="inputId"
1009
+ [formField]="f"
941
1010
  [label]="(label() | dynamicText | async) ?? undefined"
942
1011
  [labelPlacement]="props()?.labelPlacement ?? 'stacked'"
943
1012
  [step]="props()?.step ?? 1"
@@ -955,15 +1024,17 @@ class IonicSliderFieldComponent {
955
1024
  @for (error of errorsToDisplay(); track error.kind; let i = $index) {
956
1025
  <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
957
1026
  }
958
- `, 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 });
1027
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonRange, selector: "ion-range", inputs: ["activeBarStart", "color", "debounce", "disabled", "dualKnobs", "label", "labelPlacement", "max", "min", "mode", "name", "pin", "pinFormatter", "snaps", "step", "ticks", "value"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
959
1028
  }
960
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicSliderFieldComponent, decorators: [{
1029
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicSliderFieldComponent, decorators: [{
961
1030
  type: Component,
962
- args: [{ selector: 'df-ionic-slider', imports: [IonRange, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
1031
+ args: [{ selector: 'df-ion-slider', imports: [IonRange, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
963
1032
  @let f = field();
1033
+ @let inputId = key() + '-input';
964
1034
 
965
1035
  <ion-range
966
- [field]="f"
1036
+ [id]="inputId"
1037
+ [formField]="f"
967
1038
  [label]="(label() | dynamicText | async) ?? undefined"
968
1039
  [labelPlacement]="props()?.labelPlacement ?? 'stacked'"
969
1040
  [step]="props()?.step ?? 1"
@@ -986,8 +1057,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
986
1057
  '[id]': '`${key()}`',
987
1058
  '[attr.data-testid]': 'key()',
988
1059
  '[attr.hidden]': 'field()().hidden() || null',
989
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}:host([hidden]){display:none!important}\n"] }]
990
- }], 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 }] }] } });
1060
+ }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
1061
+ }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
991
1062
 
992
1063
  var ionicSlider_component = /*#__PURE__*/Object.freeze({
993
1064
  __proto__: null,
@@ -995,6 +1066,7 @@ var ionicSlider_component = /*#__PURE__*/Object.freeze({
995
1066
  });
996
1067
 
997
1068
  class IonicTextareaFieldComponent {
1069
+ elementRef = inject((ElementRef));
998
1070
  field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
999
1071
  key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
1000
1072
  label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
@@ -1002,11 +1074,18 @@ class IonicTextareaFieldComponent {
1002
1074
  className = input('', ...(ngDevMode ? [{ debugName: "className" }] : []));
1003
1075
  tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : []));
1004
1076
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : []));
1077
+ meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : []));
1005
1078
  validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : []));
1006
1079
  defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : []));
1007
1080
  resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
1008
1081
  showErrors = shouldShowErrors(this.field);
1009
1082
  errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : []));
1083
+ constructor() {
1084
+ // Shadow DOM - apply meta to ion-textarea element
1085
+ setupMetaTracking(this.elementRef, this.meta, {
1086
+ selector: 'ion-textarea',
1087
+ });
1088
+ }
1010
1089
  // ─────────────────────────────────────────────────────────────────────────────
1011
1090
  // Accessibility
1012
1091
  // ─────────────────────────────────────────────────────────────────────────────
@@ -1021,12 +1100,16 @@ class IonicTextareaFieldComponent {
1021
1100
  isRequired = computed(() => {
1022
1101
  return this.field()().required?.() === true;
1023
1102
  }, ...(ngDevMode ? [{ debugName: "isRequired" }] : []));
1024
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicTextareaFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1025
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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: `
1103
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicTextareaFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1104
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: IonicTextareaFieldComponent, isStandalone: true, selector: "df-ion-textarea", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
1026
1105
  @let f = field();
1106
+ @let ariaInvalid = isAriaInvalid();
1107
+ @let ariaRequired = isRequired() || null;
1108
+ @let textareaId = key() + '-textarea';
1027
1109
 
1028
1110
  <ion-textarea
1029
- [field]="f"
1111
+ [id]="textareaId"
1112
+ [formField]="f"
1030
1113
  [label]="(label() | dynamicText | async) ?? undefined"
1031
1114
  [labelPlacement]="props()?.labelPlacement ?? 'stacked'"
1032
1115
  [placeholder]="(placeholder() | dynamicText | async) ?? ''"
@@ -1038,28 +1121,26 @@ class IonicTextareaFieldComponent {
1038
1121
  [shape]="props()?.shape"
1039
1122
  [readonly]="f().readonly()"
1040
1123
  [helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
1041
- [errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
1042
1124
  [attr.tabindex]="tabIndex()"
1043
- [attr.aria-invalid]="isAriaInvalid()"
1044
- [attr.aria-required]="isRequired() || null"
1045
- [class.ion-invalid]="f().invalid()"
1046
- [class.ion-touched]="f().touched()"
1047
- >
1048
- <div slot="error">
1049
- @for (error of errorsToDisplay(); track error.kind; let i = $index) {
1050
- <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
1051
- }
1052
- </div>
1053
- </ion-textarea>
1054
- `, 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 });
1125
+ [attr.aria-invalid]="ariaInvalid"
1126
+ [attr.aria-required]="ariaRequired"
1127
+ />
1128
+ @for (error of errorsToDisplay(); track error.kind; let i = $index) {
1129
+ <ion-note color="danger" class="df-ion-error" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
1130
+ }
1131
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1055
1132
  }
1056
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicTextareaFieldComponent, decorators: [{
1133
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicTextareaFieldComponent, decorators: [{
1057
1134
  type: Component,
1058
- args: [{ selector: 'df-ionic-textarea', imports: [IonTextarea, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
1135
+ args: [{ selector: 'df-ion-textarea', imports: [IonTextarea, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
1059
1136
  @let f = field();
1137
+ @let ariaInvalid = isAriaInvalid();
1138
+ @let ariaRequired = isRequired() || null;
1139
+ @let textareaId = key() + '-textarea';
1060
1140
 
1061
1141
  <ion-textarea
1062
- [field]="f"
1142
+ [id]="textareaId"
1143
+ [formField]="f"
1063
1144
  [label]="(label() | dynamicText | async) ?? undefined"
1064
1145
  [labelPlacement]="props()?.labelPlacement ?? 'stacked'"
1065
1146
  [placeholder]="(placeholder() | dynamicText | async) ?? ''"
@@ -1071,26 +1152,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
1071
1152
  [shape]="props()?.shape"
1072
1153
  [readonly]="f().readonly()"
1073
1154
  [helperText]="(props()?.helperText | dynamicText | async) ?? undefined"
1074
- [errorText]="f().invalid() && f().touched() ? ((props()?.errorText | dynamicText | async) ?? undefined) : undefined"
1075
1155
  [attr.tabindex]="tabIndex()"
1076
- [attr.aria-invalid]="isAriaInvalid()"
1077
- [attr.aria-required]="isRequired() || null"
1078
- [class.ion-invalid]="f().invalid()"
1079
- [class.ion-touched]="f().touched()"
1080
- >
1081
- <div slot="error">
1082
- @for (error of errorsToDisplay(); track error.kind; let i = $index) {
1083
- <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
1084
- }
1085
- </div>
1086
- </ion-textarea>
1156
+ [attr.aria-invalid]="ariaInvalid"
1157
+ [attr.aria-required]="ariaRequired"
1158
+ />
1159
+ @for (error of errorsToDisplay(); track error.kind; let i = $index) {
1160
+ <ion-note color="danger" class="df-ion-error" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
1161
+ }
1087
1162
  `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
1088
1163
  '[id]': '`${key()}`',
1089
1164
  '[attr.data-testid]': 'key()',
1090
1165
  '[class]': 'className()',
1091
1166
  '[attr.hidden]': 'field()().hidden() || null',
1092
- }, styles: [":host([hidden]){display:none!important}\n"] }]
1093
- }], 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 }] }] } });
1167
+ }, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host([hidden]){display:none!important}\n"] }]
1168
+ }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
1094
1169
 
1095
1170
  var ionicTextarea_component = /*#__PURE__*/Object.freeze({
1096
1171
  __proto__: null,
@@ -1105,6 +1180,7 @@ var ionicTextarea_component = /*#__PURE__*/Object.freeze({
1105
1180
  * The Field directive binds to the `checked` model for checkbox controls.
1106
1181
  */
1107
1182
  class IonicToggleControlComponent {
1183
+ elementRef = inject((ElementRef));
1108
1184
  // ─────────────────────────────────────────────────────────────────────────────
1109
1185
  // FormCheckboxControl implementation
1110
1186
  // ─────────────────────────────────────────────────────────────────────────────
@@ -1128,6 +1204,13 @@ class IonicToggleControlComponent {
1128
1204
  color = input('primary', ...(ngDevMode ? [{ debugName: "color" }] : []));
1129
1205
  enableOnOffLabels = input(false, ...(ngDevMode ? [{ debugName: "enableOnOffLabels" }] : []));
1130
1206
  tabIndex = input(undefined, ...(ngDevMode ? [{ debugName: "tabIndex" }] : []));
1207
+ meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : []));
1208
+ constructor() {
1209
+ // Shadow DOM - apply meta to ion-toggle element
1210
+ setupMetaTracking(this.elementRef, this.meta, {
1211
+ selector: 'ion-toggle',
1212
+ });
1213
+ }
1131
1214
  // ─────────────────────────────────────────────────────────────────────────────
1132
1215
  // Computed ARIA attributes
1133
1216
  // ─────────────────────────────────────────────────────────────────────────────
@@ -1165,8 +1248,8 @@ class IonicToggleControlComponent {
1165
1248
  onBlur() {
1166
1249
  this.touched.set(true);
1167
1250
  }
1168
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicToggleControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1169
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", 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: `
1251
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicToggleControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1252
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.8", type: IonicToggleControlComponent, isStandalone: true, selector: "df-ion-toggle-control", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, labelPlacement: { classPropertyName: "labelPlacement", publicName: "labelPlacement", isSignal: true, isRequired: false, transformFunction: null }, justify: { classPropertyName: "justify", publicName: "justify", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, enableOnOffLabels: { classPropertyName: "enableOnOffLabels", publicName: "enableOnOffLabels", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", touched: "touchedChange" }, ngImport: i0, template: `
1170
1253
  <ion-toggle
1171
1254
  [checked]="isChecked()"
1172
1255
  (ionChange)="onToggleChange($event)"
@@ -1183,14 +1266,11 @@ class IonicToggleControlComponent {
1183
1266
  >
1184
1267
  <ng-content />
1185
1268
  </ion-toggle>
1186
- `, 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 });
1269
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n"], dependencies: [{ kind: "component", type: IonToggle, selector: "ion-toggle", inputs: ["checked", "color", "disabled", "enableOnOffLabels", "errorText", "helperText", "justify", "labelPlacement", "mode", "name", "value"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1187
1270
  }
1188
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicToggleControlComponent, decorators: [{
1271
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicToggleControlComponent, decorators: [{
1189
1272
  type: Component,
1190
- args: [{
1191
- selector: 'df-ionic-toggle-control',
1192
- imports: [IonToggle],
1193
- template: `
1273
+ args: [{ selector: 'df-ion-toggle-control', imports: [IonToggle], template: `
1194
1274
  <ion-toggle
1195
1275
  [checked]="isChecked()"
1196
1276
  (ionChange)="onToggleChange($event)"
@@ -1207,12 +1287,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
1207
1287
  >
1208
1288
  <ng-content />
1209
1289
  </ion-toggle>
1210
- `,
1211
- changeDetection: ChangeDetectionStrategy.OnPush,
1212
- }]
1213
- }], 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 }] }] } });
1290
+ `, host: {}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n"] }]
1291
+ }], ctorParameters: () => [], 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 }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }] } });
1214
1292
 
1215
1293
  class IonicToggleFieldComponent {
1294
+ elementRef = inject((ElementRef));
1216
1295
  field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
1217
1296
  key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
1218
1297
  // Properties
@@ -1221,8 +1300,12 @@ class IonicToggleFieldComponent {
1221
1300
  className = input('', ...(ngDevMode ? [{ debugName: "className" }] : []));
1222
1301
  tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : []));
1223
1302
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : []));
1303
+ meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : []));
1224
1304
  validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : []));
1225
1305
  defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : []));
1306
+ constructor() {
1307
+ setupMetaTracking(this.elementRef, this.meta);
1308
+ }
1226
1309
  resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
1227
1310
  showErrors = shouldShowErrors(this.field);
1228
1311
  errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : []));
@@ -1231,12 +1314,15 @@ class IonicToggleFieldComponent {
1231
1314
  // ─────────────────────────────────────────────────────────────────────────────
1232
1315
  /** Base ID for error elements */
1233
1316
  errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
1234
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicToggleFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1235
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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: `
1317
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicToggleFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1318
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: IonicToggleFieldComponent, isStandalone: true, selector: "df-ion-toggle", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
1236
1319
  @let f = field();
1320
+ @let toggleId = key() + '-toggle';
1237
1321
 
1238
- <df-ionic-toggle-control
1239
- [field]="f"
1322
+ <df-ion-toggle-control
1323
+ [id]="toggleId"
1324
+ [formField]="f"
1325
+ [meta]="meta()"
1240
1326
  [labelPlacement]="props()?.labelPlacement ?? 'end'"
1241
1327
  [justify]="props()?.justify"
1242
1328
  [color]="props()?.color ?? 'primary'"
@@ -1244,20 +1330,23 @@ class IonicToggleFieldComponent {
1244
1330
  [tabIndex]="tabIndex()"
1245
1331
  >
1246
1332
  {{ label() | dynamicText | async }}
1247
- </df-ionic-toggle-control>
1333
+ </df-ion-toggle-control>
1248
1334
 
1249
1335
  @for (error of errorsToDisplay(); track error.kind; let i = $index) {
1250
1336
  <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
1251
1337
  }
1252
- `, 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 });
1338
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonicToggleControlComponent, selector: "df-ion-toggle-control", inputs: ["checked", "touched", "disabled", "readonly", "invalid", "required", "labelPlacement", "justify", "color", "enableOnOffLabels", "tabIndex", "meta"], outputs: ["checkedChange", "touchedChange"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1253
1339
  }
1254
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IonicToggleFieldComponent, decorators: [{
1340
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: IonicToggleFieldComponent, decorators: [{
1255
1341
  type: Component,
1256
- args: [{ selector: 'df-ionic-toggle', imports: [IonicToggleControlComponent, IonNote, Field, DynamicTextPipe, AsyncPipe], template: `
1342
+ args: [{ selector: 'df-ion-toggle', imports: [IonicToggleControlComponent, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
1257
1343
  @let f = field();
1344
+ @let toggleId = key() + '-toggle';
1258
1345
 
1259
- <df-ionic-toggle-control
1260
- [field]="f"
1346
+ <df-ion-toggle-control
1347
+ [id]="toggleId"
1348
+ [formField]="f"
1349
+ [meta]="meta()"
1261
1350
  [labelPlacement]="props()?.labelPlacement ?? 'end'"
1262
1351
  [justify]="props()?.justify"
1263
1352
  [color]="props()?.color ?? 'primary'"
@@ -1265,7 +1354,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
1265
1354
  [tabIndex]="tabIndex()"
1266
1355
  >
1267
1356
  {{ label() | dynamicText | async }}
1268
- </df-ionic-toggle-control>
1357
+ </df-ion-toggle-control>
1269
1358
 
1270
1359
  @for (error of errorsToDisplay(); track error.kind; let i = $index) {
1271
1360
  <ion-note color="danger" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</ion-note>
@@ -1275,8 +1364,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
1275
1364
  '[id]': '`${key()}`',
1276
1365
  '[attr.data-testid]': 'key()',
1277
1366
  '[attr.hidden]': 'field()().hidden() || null',
1278
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}:host([hidden]){display:none!important}\n"] }]
1279
- }], 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 }] }] } });
1367
+ }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
1368
+ }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
1280
1369
 
1281
1370
  var ionicToggle_component = /*#__PURE__*/Object.freeze({
1282
1371
  __proto__: null,
@@ -1572,6 +1661,7 @@ const IONIC_FIELD_TYPES = [
1572
1661
  name: IonicField.Input,
1573
1662
  loadComponent: () => Promise.resolve().then(function () { return ionicInput_component; }),
1574
1663
  mapper: valueFieldMapper,
1664
+ propsToMeta: ['type'],
1575
1665
  },
1576
1666
  {
1577
1667
  name: IonicField.Select,
@@ -1623,6 +1713,7 @@ const IONIC_FIELD_TYPES = [
1623
1713
  name: IonicField.Textarea,
1624
1714
  loadComponent: () => Promise.resolve().then(function () { return ionicTextarea_component; }),
1625
1715
  mapper: valueFieldMapper,
1716
+ propsToMeta: ['rows'],
1626
1717
  },
1627
1718
  {
1628
1719
  name: IonicField.Radio,