@ng-forge/dynamic-forms-ionic 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-forge/dynamic-forms-ionic",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Ionic integration for @ng-forge/dynamic-forms. Pre-built Ionic form components for mobile and desktop.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -24,16 +24,16 @@
24
24
  "form-builder",
25
25
  "ng-forge"
26
26
  ],
27
- "sideEffects": false,
27
+ "sideEffects": true,
28
28
  "engines": {
29
- "node": ">=18"
29
+ "node": ">=20"
30
30
  },
31
31
  "peerDependencies": {
32
- "@angular/common": ">=21.0.7",
33
- "@angular/core": ">=21.0.7",
34
- "@angular/forms": ">=21.0.7",
32
+ "@angular/common": "~21.1.0",
33
+ "@angular/core": "~21.1.0",
34
+ "@angular/forms": "~21.1.0",
35
35
  "@ionic/angular": ">=7.0.0",
36
- "@ng-forge/dynamic-forms": "~0.3.0",
36
+ "@ng-forge/dynamic-forms": "~0.4.0",
37
37
  "rxjs": ">=7.0.0"
38
38
  },
39
39
  "dependencies": {
@@ -1,4 +1,4 @@
1
- import { FormEvent, FieldDef, LogicConfig, FieldComponent, DynamicText, FormEventConstructor, ArrayItemContext, CheckedFieldComponent, FieldMeta, ValidationMessages, ValueFieldComponent, ValueType, FieldOption, FieldTypeDefinition } from '@ng-forge/dynamic-forms';
1
+ import { FormEvent, FieldDef, LogicConfig, FieldComponent, DynamicText, FormEventConstructor, ArrayItemContext, CheckedFieldComponent, FieldMeta, ValidationMessages, ValueFieldComponent, ValueType, FieldOption, FieldTypeDefinition, NarrowFields, RegisteredFieldTypes, InferFormValue, FormConfig } from '@ng-forge/dynamic-forms';
2
2
  import * as _ng_forge_dynamic_forms_integration from '@ng-forge/dynamic-forms/integration';
3
3
  import { ButtonField, EventArgs, CheckboxField, DatepickerField, DatepickerProps, InputMeta, InputField, InputProps, MultiCheckboxField, RadioField, SelectField, SelectProps, SliderField, TextareaField, TextareaProps, TextareaMeta, ToggleField } from '@ng-forge/dynamic-forms/integration';
4
4
  import * as _angular_core from '@angular/core';
@@ -114,6 +114,7 @@ interface IonicCheckboxProps {
114
114
  justify?: 'start' | 'end' | 'space-between';
115
115
  color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
116
116
  indeterminate?: boolean;
117
+ hint?: DynamicText;
117
118
  }
118
119
  type IonicCheckboxField = CheckboxField<IonicCheckboxProps>;
119
120
  type IonicCheckboxComponent = CheckedFieldComponent<IonicCheckboxField>;
@@ -135,11 +136,15 @@ declare class IonicCheckboxFieldComponent implements IonicCheckboxComponent {
135
136
  readonly errorsToDisplay: _angular_core.Signal<_ng_forge_dynamic_forms_integration.ResolvedError[]>;
136
137
  constructor();
137
138
  /** Base ID for error elements */
138
- readonly errorId: _angular_core.Signal<string>;
139
+ protected readonly errorId: _angular_core.Signal<string>;
140
+ /** Unique ID for the helper text element */
141
+ protected readonly hintId: _angular_core.Signal<string>;
139
142
  /** Whether the field is currently in an invalid state (invalid AND touched) */
140
- readonly isAriaInvalid: _angular_core.Signal<boolean>;
143
+ protected readonly ariaInvalid: _angular_core.Signal<boolean>;
141
144
  /** Whether the field has a required validator */
142
- readonly isRequired: _angular_core.Signal<boolean>;
145
+ protected readonly ariaRequired: _angular_core.Signal<true | null>;
146
+ /** aria-describedby linking to hint OR error elements (mutually exclusive) */
147
+ protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
143
148
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicCheckboxFieldComponent, never>;
144
149
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicCheckboxFieldComponent, "df-ion-checkbox", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
145
150
  }
@@ -156,6 +161,7 @@ interface IonicDatepickerProps extends DatepickerProps {
156
161
  cancelText?: string;
157
162
  size?: 'cover' | 'fixed';
158
163
  color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
164
+ hint?: DynamicText;
159
165
  }
160
166
  type IonicDatepickerField = DatepickerField<IonicDatepickerProps>;
161
167
  type IonicDatepickerComponent = ValueFieldComponent<IonicDatepickerField>;
@@ -181,11 +187,15 @@ declare class IonicDatepickerFieldComponent implements IonicDatepickerComponent
181
187
  readonly isModalOpen: _angular_core.WritableSignal<boolean>;
182
188
  constructor();
183
189
  /** Base ID for error elements */
184
- readonly errorId: _angular_core.Signal<string>;
190
+ protected readonly errorId: _angular_core.Signal<string>;
191
+ /** Unique ID for the helper text element */
192
+ protected readonly hintId: _angular_core.Signal<string>;
185
193
  /** Whether the field is currently in an invalid state (invalid AND touched) */
186
- readonly isAriaInvalid: _angular_core.Signal<boolean>;
194
+ protected readonly ariaInvalid: _angular_core.Signal<boolean>;
187
195
  /** Whether the field has a required validator */
188
- readonly isRequired: _angular_core.Signal<boolean>;
196
+ protected readonly ariaRequired: _angular_core.Signal<true | null>;
197
+ /** aria-describedby linking to hint OR error elements (mutually exclusive) */
198
+ protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
189
199
  openModal(): void;
190
200
  closeModal(): void;
191
201
  onDateChange(event: CustomEvent): void;
@@ -200,7 +210,7 @@ interface IonicInputProps extends InputProps {
200
210
  shape?: 'round';
201
211
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked' | 'floating';
202
212
  color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
203
- helperText?: DynamicText;
213
+ hint?: DynamicText;
204
214
  errorText?: DynamicText;
205
215
  counter?: boolean;
206
216
  maxlength?: number;
@@ -232,33 +242,38 @@ declare class IonicInputFieldComponent implements IonicInputComponent {
232
242
  readonly errorsToDisplay: _angular_core.Signal<_ng_forge_dynamic_forms_integration.ResolvedError[]>;
233
243
  constructor();
234
244
  /** Base ID for error elements */
235
- readonly errorId: _angular_core.Signal<string>;
245
+ protected readonly errorId: _angular_core.Signal<string>;
246
+ /** Unique ID for the helper text element */
247
+ protected readonly hintId: _angular_core.Signal<string>;
236
248
  /** Whether the field is currently in an invalid state (invalid AND touched) */
237
- readonly isAriaInvalid: _angular_core.Signal<boolean>;
249
+ protected readonly ariaInvalid: _angular_core.Signal<boolean>;
238
250
  /** Whether the field has a required validator */
239
- readonly isRequired: _angular_core.Signal<boolean>;
251
+ protected readonly ariaRequired: _angular_core.Signal<true | null>;
252
+ /** aria-describedby linking to hint OR error elements (mutually exclusive) */
253
+ protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
240
254
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicInputFieldComponent, never>;
241
255
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicInputFieldComponent, "df-ion-input", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
242
256
  }
243
257
 
244
- interface IonicMultiCheckboxProps<T> {
258
+ interface IonicMultiCheckboxProps {
245
259
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
246
260
  justify?: 'start' | 'end' | 'space-between';
247
261
  color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
262
+ hint?: DynamicText;
248
263
  }
249
- type IonicMultiCheckboxField<T> = MultiCheckboxField<T, IonicMultiCheckboxProps<T>>;
250
- type IonicMultiCheckboxComponent<T> = ValueFieldComponent<IonicMultiCheckboxField<T>>;
264
+ type IonicMultiCheckboxField<T> = MultiCheckboxField<T, IonicMultiCheckboxProps>;
265
+ type IonicMultiCheckboxComponent = ValueFieldComponent<IonicMultiCheckboxField<ValueType>>;
251
266
 
252
- declare class IonicMultiCheckboxFieldComponent<T extends ValueType> implements IonicMultiCheckboxComponent<T> {
267
+ declare class IonicMultiCheckboxFieldComponent implements IonicMultiCheckboxComponent {
253
268
  private readonly elementRef;
254
- readonly field: _angular_core.InputSignal<FieldTree<T[]>>;
269
+ readonly field: _angular_core.InputSignal<FieldTree<ValueType[]>>;
255
270
  readonly key: _angular_core.InputSignal<string>;
256
271
  readonly label: _angular_core.InputSignal<DynamicText | undefined>;
257
272
  readonly placeholder: _angular_core.InputSignal<DynamicText | undefined>;
258
273
  readonly className: _angular_core.InputSignal<string>;
259
274
  readonly tabIndex: _angular_core.InputSignal<number | undefined>;
260
- readonly options: _angular_core.InputSignal<FieldOption<T>[]>;
261
- readonly props: _angular_core.InputSignal<IonicMultiCheckboxProps<T> | undefined>;
275
+ readonly options: _angular_core.InputSignal<FieldOption<ValueType>[]>;
276
+ readonly props: _angular_core.InputSignal<IonicMultiCheckboxProps | undefined>;
262
277
  readonly meta: _angular_core.InputSignal<FieldMeta | undefined>;
263
278
  readonly validationMessages: _angular_core.InputSignal<ValidationMessages | undefined>;
264
279
  readonly defaultValidationMessages: _angular_core.InputSignal<ValidationMessages | undefined>;
@@ -266,37 +281,44 @@ declare class IonicMultiCheckboxFieldComponent<T extends ValueType> implements I
266
281
  readonly showErrors: _angular_core.Signal<boolean>;
267
282
  readonly errorsToDisplay: _angular_core.Signal<_ng_forge_dynamic_forms_integration.ResolvedError[]>;
268
283
  /** Base ID for error elements */
269
- readonly errorId: _angular_core.Signal<string>;
284
+ protected readonly errorId: _angular_core.Signal<string>;
285
+ /** Unique ID for the helper text element */
286
+ protected readonly hintId: _angular_core.Signal<string>;
270
287
  /** Whether the field is currently in an invalid state (invalid AND touched) */
271
- readonly isAriaInvalid: _angular_core.Signal<boolean>;
288
+ protected readonly ariaInvalid: _angular_core.Signal<boolean>;
272
289
  /** Whether the field has a required validator */
273
- readonly isRequired: _angular_core.Signal<boolean>;
274
- valueViewModel: _angular_core.WritableSignal<FieldOption<T>[]>;
290
+ protected readonly ariaRequired: _angular_core.Signal<true | null>;
291
+ /** aria-describedby linking to hint OR error elements (mutually exclusive) */
292
+ protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
293
+ valueViewModel: _angular_core.WritableSignal<FieldOption<ValueType>[]>;
294
+ /** Computed map of checked option values for O(1) lookup in template */
295
+ readonly checkedValuesMap: _angular_core.Signal<Record<string, boolean>>;
275
296
  constructor();
276
- onCheckboxChange(option: FieldOption<T>, checked: boolean): void;
277
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicMultiCheckboxFieldComponent<any>, never>;
278
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicMultiCheckboxFieldComponent<any>, "df-ion-multi-checkbox", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
297
+ onCheckboxChange(option: FieldOption<ValueType>, checked: boolean): void;
298
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicMultiCheckboxFieldComponent, never>;
299
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicMultiCheckboxFieldComponent, "df-ion-multi-checkbox", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
279
300
  }
280
301
 
281
- interface IonicRadioProps<T> {
302
+ interface IonicRadioProps {
282
303
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
283
304
  justify?: 'start' | 'end' | 'space-between';
284
305
  color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
285
- compareWith?: (o1: T, o2: T) => boolean;
306
+ compareWith?: (o1: ValueType, o2: ValueType) => boolean;
307
+ hint?: DynamicText;
286
308
  }
287
- type IonicRadioField<T> = RadioField<T, IonicRadioProps<T>>;
288
- type IonicRadioComponent<T> = ValueFieldComponent<IonicRadioField<T>>;
309
+ type IonicRadioField<T> = RadioField<T, IonicRadioProps>;
310
+ type IonicRadioComponent = ValueFieldComponent<IonicRadioField<ValueType>>;
289
311
 
290
- declare class IonicRadioFieldComponent<T> implements IonicRadioComponent<T> {
312
+ declare class IonicRadioFieldComponent implements IonicRadioComponent {
291
313
  private readonly elementRef;
292
- readonly field: _angular_core.InputSignal<FieldTree<T>>;
314
+ readonly field: _angular_core.InputSignal<FieldTree<ValueType>>;
293
315
  readonly key: _angular_core.InputSignal<string>;
294
316
  readonly label: _angular_core.InputSignal<DynamicText | undefined>;
295
317
  readonly placeholder: _angular_core.InputSignal<DynamicText | undefined>;
296
318
  readonly className: _angular_core.InputSignal<string>;
297
319
  readonly tabIndex: _angular_core.InputSignal<number | undefined>;
298
- readonly options: _angular_core.InputSignal<FieldOption<T>[]>;
299
- readonly props: _angular_core.InputSignal<IonicRadioProps<T> | undefined>;
320
+ readonly options: _angular_core.InputSignal<FieldOption<ValueType>[]>;
321
+ readonly props: _angular_core.InputSignal<IonicRadioProps | undefined>;
300
322
  readonly meta: _angular_core.InputSignal<FieldMeta | undefined>;
301
323
  readonly validationMessages: _angular_core.InputSignal<ValidationMessages | undefined>;
302
324
  readonly defaultValidationMessages: _angular_core.InputSignal<ValidationMessages | undefined>;
@@ -306,16 +328,20 @@ declare class IonicRadioFieldComponent<T> implements IonicRadioComponent<T> {
306
328
  defaultCompare: (value1: any, value2: any) => boolean;
307
329
  constructor();
308
330
  /** Base ID for error elements */
309
- readonly errorId: _angular_core.Signal<string>;
331
+ protected readonly errorId: _angular_core.Signal<string>;
332
+ /** Unique ID for the helper text element */
333
+ protected readonly hintId: _angular_core.Signal<string>;
310
334
  /** Whether the field is currently in an invalid state (invalid AND touched) */
311
- readonly isAriaInvalid: _angular_core.Signal<boolean>;
335
+ protected readonly ariaInvalid: _angular_core.Signal<boolean>;
312
336
  /** Whether the field has a required validator */
313
- readonly isRequired: _angular_core.Signal<boolean>;
314
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicRadioFieldComponent<any>, never>;
315
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicRadioFieldComponent<any>, "df-ion-radio", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
337
+ protected readonly ariaRequired: _angular_core.Signal<true | null>;
338
+ /** aria-describedby linking to hint OR error elements (mutually exclusive) */
339
+ protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
340
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicRadioFieldComponent, never>;
341
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicRadioFieldComponent, "df-ion-radio", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
316
342
  }
317
343
 
318
- interface IonicSelectProps<T> extends SelectProps {
344
+ interface IonicSelectProps extends SelectProps {
319
345
  multiple?: boolean;
320
346
  interface?: 'action-sheet' | 'popover' | 'alert';
321
347
  interfaceOptions?: unknown;
@@ -326,21 +352,22 @@ interface IonicSelectProps<T> extends SelectProps {
326
352
  shape?: 'round';
327
353
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked' | 'floating';
328
354
  color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
329
- compareWith?: (o1: T, o2: T) => boolean;
355
+ compareWith?: (o1: ValueType, o2: ValueType) => boolean;
356
+ hint?: DynamicText;
330
357
  }
331
- type IonicSelectField<T> = SelectField<T, IonicSelectProps<T>>;
332
- type IonicSelectComponent<T> = ValueFieldComponent<IonicSelectField<T>>;
358
+ type IonicSelectField<T> = SelectField<T, IonicSelectProps>;
359
+ type IonicSelectComponent = ValueFieldComponent<IonicSelectField<ValueType>>;
333
360
 
334
- declare class IonicSelectFieldComponent<T> implements IonicSelectComponent<T> {
361
+ declare class IonicSelectFieldComponent implements IonicSelectComponent {
335
362
  private readonly elementRef;
336
- readonly field: _angular_core.InputSignal<FieldTree<T>>;
363
+ readonly field: _angular_core.InputSignal<FieldTree<ValueType>>;
337
364
  readonly key: _angular_core.InputSignal<string>;
338
365
  readonly label: _angular_core.InputSignal<DynamicText | undefined>;
339
366
  readonly placeholder: _angular_core.InputSignal<DynamicText | undefined>;
340
367
  readonly className: _angular_core.InputSignal<string>;
341
368
  readonly tabIndex: _angular_core.InputSignal<number | undefined>;
342
- readonly options: _angular_core.InputSignal<FieldOption<T>[]>;
343
- readonly props: _angular_core.InputSignal<IonicSelectProps<T> | undefined>;
369
+ readonly options: _angular_core.InputSignal<FieldOption<ValueType>[]>;
370
+ readonly props: _angular_core.InputSignal<IonicSelectProps | undefined>;
344
371
  readonly meta: _angular_core.InputSignal<FieldMeta | undefined>;
345
372
  readonly validationMessages: _angular_core.InputSignal<ValidationMessages | undefined>;
346
373
  readonly defaultValidationMessages: _angular_core.InputSignal<ValidationMessages | undefined>;
@@ -350,13 +377,17 @@ declare class IonicSelectFieldComponent<T> implements IonicSelectComponent<T> {
350
377
  readonly errorsToDisplay: _angular_core.Signal<_ng_forge_dynamic_forms_integration.ResolvedError[]>;
351
378
  defaultCompare: (value1: any, value2: any) => boolean;
352
379
  /** Base ID for error elements */
353
- readonly errorId: _angular_core.Signal<string>;
380
+ protected readonly errorId: _angular_core.Signal<string>;
381
+ /** Unique ID for the helper text element */
382
+ protected readonly hintId: _angular_core.Signal<string>;
354
383
  /** Whether the field is currently in an invalid state (invalid AND touched) */
355
- readonly isAriaInvalid: _angular_core.Signal<boolean>;
384
+ protected readonly ariaInvalid: _angular_core.Signal<boolean>;
356
385
  /** Whether the field has a required validator */
357
- readonly isRequired: _angular_core.Signal<boolean>;
358
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicSelectFieldComponent<any>, never>;
359
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicSelectFieldComponent<any>, "df-ion-select", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
386
+ protected readonly ariaRequired: _angular_core.Signal<true | null>;
387
+ /** aria-describedby linking to hint OR error elements (mutually exclusive) */
388
+ protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
389
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicSelectFieldComponent, never>;
390
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicSelectFieldComponent, "df-ion-select", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
360
391
  }
361
392
 
362
393
  interface IonicSliderProps {
@@ -370,6 +401,7 @@ interface IonicSliderProps {
370
401
  snaps?: boolean;
371
402
  color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
372
403
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
404
+ hint?: DynamicText;
373
405
  }
374
406
  type IonicSliderField = SliderField<IonicSliderProps>;
375
407
  type IonicSliderComponent = ValueFieldComponent<IonicSliderField>;
@@ -392,11 +424,15 @@ declare class IonicSliderFieldComponent implements IonicSliderComponent {
392
424
  readonly errorsToDisplay: _angular_core.Signal<_ng_forge_dynamic_forms_integration.ResolvedError[]>;
393
425
  protected defaultPinFormatter: (value: number) => string;
394
426
  /** Base ID for error elements */
395
- readonly errorId: _angular_core.Signal<string>;
427
+ protected readonly errorId: _angular_core.Signal<string>;
428
+ /** Unique ID for the helper text element */
429
+ protected readonly hintId: _angular_core.Signal<string>;
396
430
  /** Whether the field is currently in an invalid state (invalid AND touched) */
397
- readonly isAriaInvalid: _angular_core.Signal<boolean>;
431
+ protected readonly ariaInvalid: _angular_core.Signal<boolean>;
398
432
  /** Whether the field has a required validator */
399
- readonly isRequired: _angular_core.Signal<boolean>;
433
+ protected readonly ariaRequired: _angular_core.Signal<true | null>;
434
+ /** aria-describedby linking to hint OR error elements (mutually exclusive) */
435
+ protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
400
436
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicSliderFieldComponent, never>;
401
437
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicSliderFieldComponent, "df-ion-slider", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
402
438
  }
@@ -409,7 +445,7 @@ interface IonicTextareaProps extends TextareaProps {
409
445
  fill?: 'solid' | 'outline';
410
446
  shape?: 'round';
411
447
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked' | 'floating';
412
- helperText?: DynamicText;
448
+ hint?: DynamicText;
413
449
  errorText?: DynamicText;
414
450
  color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
415
451
  }
@@ -433,11 +469,15 @@ declare class IonicTextareaFieldComponent implements IonicTextareaComponent {
433
469
  readonly errorsToDisplay: _angular_core.Signal<_ng_forge_dynamic_forms_integration.ResolvedError[]>;
434
470
  constructor();
435
471
  /** Base ID for error elements */
436
- readonly errorId: _angular_core.Signal<string>;
472
+ protected readonly errorId: _angular_core.Signal<string>;
473
+ /** Unique ID for the helper text element */
474
+ protected readonly hintId: _angular_core.Signal<string>;
437
475
  /** Whether the field is currently in an invalid state (invalid AND touched) */
438
- readonly isAriaInvalid: _angular_core.Signal<boolean>;
476
+ protected readonly ariaInvalid: _angular_core.Signal<boolean>;
439
477
  /** Whether the field has a required validator */
440
- readonly isRequired: _angular_core.Signal<boolean>;
478
+ protected readonly ariaRequired: _angular_core.Signal<true | null>;
479
+ /** aria-describedby linking to hint OR error elements (mutually exclusive) */
480
+ protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
441
481
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicTextareaFieldComponent, never>;
442
482
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicTextareaFieldComponent, "df-ion-textarea", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
443
483
  }
@@ -447,6 +487,7 @@ interface IonicToggleProps {
447
487
  justify?: 'start' | 'end' | 'space-between';
448
488
  color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
449
489
  enableOnOffLabels?: boolean;
490
+ hint?: DynamicText;
450
491
  }
451
492
  type IonicToggleField = ToggleField<IonicToggleProps>;
452
493
  type IonicToggleComponent = CheckedFieldComponent<IonicToggleField>;
@@ -468,7 +509,11 @@ declare class IonicToggleFieldComponent implements IonicToggleComponent {
468
509
  readonly showErrors: _angular_core.Signal<boolean>;
469
510
  readonly errorsToDisplay: _angular_core.Signal<_ng_forge_dynamic_forms_integration.ResolvedError[]>;
470
511
  /** Base ID for error elements */
471
- readonly errorId: _angular_core.Signal<string>;
512
+ protected readonly errorId: _angular_core.Signal<string>;
513
+ /** Unique ID for the helper text element */
514
+ protected readonly hintId: _angular_core.Signal<string>;
515
+ /** aria-describedby linking to hint OR error elements (mutually exclusive) */
516
+ protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
472
517
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicToggleFieldComponent, never>;
473
518
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicToggleFieldComponent, "df-ion-toggle", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
474
519
  }
@@ -481,8 +526,24 @@ declare const IONIC_FIELD_TYPES: FieldTypeDefinition[];
481
526
 
482
527
  /**
483
528
  * Configuration options for Ionic form fields.
484
- * These settings will be applied as defaults to all Ionic form fields
485
- * unless overridden by individual field props.
529
+ *
530
+ * These settings can be applied at two levels:
531
+ * - **Library-level**: Via `withIonicFields({ ... })` - applies to all forms
532
+ * - **Form-level**: Via `defaultProps` in form config - applies to a specific form
533
+ *
534
+ * The cascade hierarchy is: Library-level → Form-level → Field-level
535
+ *
536
+ * @example
537
+ * ```typescript
538
+ * // Library-level (in app config)
539
+ * provideDynamicForms(withIonicFields({ fill: 'outline', labelPlacement: 'floating' }))
540
+ *
541
+ * // Form-level (in form config)
542
+ * const config: IonicFormConfig = {
543
+ * defaultProps: { color: 'tertiary' },
544
+ * fields: [...]
545
+ * };
546
+ * ```
486
547
  */
487
548
  interface IonicConfig {
488
549
  /**
@@ -573,6 +634,52 @@ declare const IonicField: {
573
634
  };
574
635
  type IonicFieldType = (typeof IonicField)[keyof typeof IonicField];
575
636
 
637
+ /**
638
+ * Ionic-specific props that can be set at form level and cascade to all fields.
639
+ *
640
+ * This is the same type as `IonicConfig` used in `withIonicFields()`.
641
+ * Using a single type ensures consistency between library-level and form-level configuration.
642
+ *
643
+ * The cascade hierarchy is: Library-level → Form-level → Field-level
644
+ *
645
+ * @example
646
+ * ```typescript
647
+ * const config: IonicFormConfig = {
648
+ * defaultProps: {
649
+ * fill: 'outline',
650
+ * labelPlacement: 'floating',
651
+ * color: 'tertiary',
652
+ * },
653
+ * fields: [
654
+ * { type: 'ionic-input', key: 'name', label: 'Name' },
655
+ * ],
656
+ * };
657
+ * ```
658
+ */
659
+ type IonicFormProps = IonicConfig;
660
+ /**
661
+ * Ionic-specific FormConfig with type-safe defaultProps.
662
+ *
663
+ * Use this type alias when defining form configurations with Ionic components
664
+ * to get IDE autocomplete and type checking for `defaultProps`.
665
+ *
666
+ * @example
667
+ * ```typescript
668
+ * const formConfig: IonicFormConfig = {
669
+ * defaultProps: {
670
+ * fill: 'outline',
671
+ * labelPlacement: 'floating',
672
+ * color: 'primary',
673
+ * },
674
+ * fields: [
675
+ * { type: 'ionic-input', key: 'name', label: 'Name' }, // Uses form defaultProps
676
+ * { type: 'ionic-input', key: 'email', props: { fill: 'solid' } }, // Override
677
+ * ],
678
+ * };
679
+ * ```
680
+ */
681
+ type IonicFormConfig<TFields extends NarrowFields | RegisteredFieldTypes[] = RegisteredFieldTypes[], TValue = InferFormValue<TFields extends readonly RegisteredFieldTypes[] ? TFields : RegisteredFieldTypes[]>> = FormConfig<TFields, TValue, IonicFormProps>;
682
+
576
683
  /**
577
684
  * Module augmentation for @ng-forge/dynamic-form
578
685
  * This file augments the FieldRegistryLeaves interface to include
@@ -666,4 +773,4 @@ declare module '@ng-forge/dynamic-forms' {
666
773
  }
667
774
 
668
775
  export { IONIC_CONFIG, IONIC_FIELD_TYPES, IonicButtonFieldComponent, IonicCheckboxFieldComponent, IonicDatepickerFieldComponent, IonicField, IonicInputFieldComponent, IonicMultiCheckboxFieldComponent, IonicRadioFieldComponent, IonicSelectFieldComponent, IonicSliderFieldComponent, IonicTextareaFieldComponent, IonicToggleFieldComponent, withIonicFields };
669
- export type { AddArrayItemButtonField, IonicButtonField, IonicButtonProps, IonicCheckboxComponent, IonicCheckboxField, IonicCheckboxProps, IonicConfig, IonicDatepickerComponent, IonicDatepickerField, IonicDatepickerProps, IonicFieldType, IonicInputComponent, IonicInputField, IonicInputProps, IonicMultiCheckboxComponent, IonicMultiCheckboxField, IonicMultiCheckboxProps, IonicNextButtonField, IonicPreviousButtonField, IonicRadioComponent, IonicRadioField, IonicRadioProps, IonicSelectComponent, IonicSelectField, IonicSelectProps, IonicSliderComponent, IonicSliderField, IonicSliderProps, IonicSubmitButtonField, IonicTextareaComponent, IonicTextareaField, IonicTextareaProps, IonicToggleComponent, IonicToggleField, IonicToggleProps, RemoveArrayItemButtonField };
776
+ export type { AddArrayItemButtonField, IonicButtonField, IonicButtonProps, IonicCheckboxComponent, IonicCheckboxField, IonicCheckboxProps, IonicConfig, IonicDatepickerComponent, IonicDatepickerField, IonicDatepickerProps, IonicFieldType, IonicFormConfig, IonicFormProps, IonicInputComponent, IonicInputField, IonicInputProps, IonicMultiCheckboxComponent, IonicMultiCheckboxField, IonicMultiCheckboxProps, IonicNextButtonField, IonicPreviousButtonField, IonicRadioComponent, IonicRadioField, IonicRadioProps, IonicSelectComponent, IonicSelectField, IonicSelectProps, IonicSliderComponent, IonicSliderField, IonicSliderProps, IonicSubmitButtonField, IonicTextareaComponent, IonicTextareaField, IonicTextareaProps, IonicToggleComponent, IonicToggleField, IonicToggleProps, RemoveArrayItemButtonField };