@ng-forge/dynamic-forms-ionic 1.2.0-next.9 → 1.3.0-next.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.
Files changed (19) hide show
  1. package/fesm2022/{ng-forge-dynamic-forms-ionic-ionic-field-errors-wrapper.component-Dl3heov4.mjs → ng-forge-dynamic-forms-ionic-ionic-field-errors-wrapper.component-CN0CagvT.mjs} +4 -4
  2. package/fesm2022/{ng-forge-dynamic-forms-ionic-ionic-field-errors-wrapper.component-Dl3heov4.mjs.map → ng-forge-dynamic-forms-ionic-ionic-field-errors-wrapper.component-CN0CagvT.mjs.map} +1 -1
  3. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-addon-button.mjs +3 -3
  4. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-addon-icon.mjs +3 -3
  5. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-button.mjs +3 -3
  6. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-checkbox.mjs +3 -3
  7. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-datepicker.mjs +3 -3
  8. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-input.mjs +3 -3
  9. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-multi-checkbox.mjs +3 -3
  10. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-radio.mjs +3 -3
  11. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-select.mjs +3 -3
  12. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-slider.mjs +3 -3
  13. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-textarea.mjs +3 -3
  14. package/fesm2022/ng-forge-dynamic-forms-ionic-lazy-toggle.mjs +6 -6
  15. package/fesm2022/ng-forge-dynamic-forms-ionic-shared.mjs +3 -3
  16. package/fesm2022/ng-forge-dynamic-forms-ionic.mjs +7 -1182
  17. package/fesm2022/ng-forge-dynamic-forms-ionic.mjs.map +1 -1
  18. package/package.json +3 -3
  19. package/types/ng-forge-dynamic-forms-ionic.d.ts +41 -169
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-ionic.mjs","mappings":";;;;;;;;;;;;;AAyCc;;AAGH;;AAEA;;AAEA;;;AAGP;;AACA;;;AAXiB;;;;;;;;;;;;;;;;;;;AAHlB;;;;AA7BS;;;;;;;;;;;;;;;;;;;;;;;ACwCE;;AAGH;;;AAHU;;;;;;;;;;;;;;;;;;;;;;;;;;AAxCT;;;;;;;;;;;;;;;;;;;;;;;;;ACgGE;;;;;;;;AAMH;;;;;AAKP;;;AAIA;;AAGF;AACE;gBAGA;AACE;AACA;;;AAEA;;;;AAKJ;AACE;AAAW;AACX;;AAGF;AACE;AAAW;;;AAKT;AACE;AACF;AACA;AACE;AACF;AACE;AACF;AACE;AACF;AACE;AACF;AACE;AACF;AACE;;;;AAxDa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AArFT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC4IE;AACK;;;;AAMR;;AAET,IAKS;;IAGQ;AAEE;;AACA;;IAEA;;AACA;;IAGA;;AAEnB;;;;;;;;;AAaA;AACE;wBAIA;;;;AAGI;AACA;;AAEI;;;AAEE;;;AAEA;;AAEJ;;AAEJ;AACF;;;AA7DiB;AA7EjB;AACE;AACA;AACD;AACD;gFAME;;AAEE;AACA;AACA;oBAEA;;AAEE;AACE;AACA;;;;;;AAOC;;;;AAIR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAnCF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIC;AACE;AACA;AACD;AACD;4IAME;;AAEE;AACA;AACA;;;AAIE;AACE;AACA;;;;;;AAOC;;;;AAIR;AACF;;;ACjCW;;;;AAIH;;AAET;AAEI;;AAEF;IAKO;;;;;AAKP;;;AAGF;AACE;AACE;AAEA;AACE;;AAEJ;AAEA;AACE;AACA;;;AAIE;;AAEJ;;;;;AAMI;;;AAEA;;AAEJ;;;AAlDiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAxET;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC6DE;;;;AAIH;;AAET;;AANmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAtBlB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACQW;;;;AAIH;;AAET;;AANmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAXlB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACMW;;AAGH;;AACA;;;;AAJU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA3CT;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACyCE;AACK;;AAIR;;AAET;wBAIE;;AAEI;AACA;;AAEI;;;AAEE;;;AAEA;;AAEJ;;AAEJ;AACF;;;AAzBiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAxCT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QC6DS;;IAGA;AACjB;;;AAGF,IAImB;;;;gBASnB;;;;AAME;;;AA7DS;;;;;;;;;;;;;;;;;;;;AAzBD;;;;;;;;;;;;;;;;;AAqBR;;;;ACiBU;;AAGH;;;AAHU;;;;;;;;;;;;;;;;;;;;;;;;;AAvCT;;;;;;;;;;;;;;;;;;;;;;;;;ACNL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACXI;AACJ;AACA;AACA;;;AAKE;AACE;AACA;;;AAKA;;;AAKA;;QAIF;AACA;;AAGI;;AACA;AACF;;;;AAKE;AACA;AACE;;;;;AAMN;AACF;AACF;;;ACvCA;;;AAIA;AACE;AACA;;AAGF;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAIA;AAEA;AAEA;AAOO;AACL;;AAEE;AACA;;AAEA;AACA;AACE;AACD;AACD;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;;AAEA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;;;;AC1JH;AACE;AACA;AACA;;AAeI;;;;AAOA;;AAE4B;AAC9B;;AAGF;AACF;AAEA;AAEA;AACE;AACA;AACA;AACE;AACE;;;;AAKN;AACE;AACA;AACA;;AAIE;AACE;;QAKF;AACE;;;;;;AAkBF;AACA;;;AAGC;;AAEL;;;;ICzDqB;;;;;;;AAKnB;;AAKmB;;AACnB,IAImB;;;AAnBR;;;;;;;;;;;;;;;;;;;;;;;;;AA1CD;;;;;;;;;;;;;;;;;;;;;;;;;;;ICWD;;;;;;AAIU;;;AAPR;;;;AATF;AACT;AACA;AACA;AACA;AACE;AACD;;AAEF","names":[],"ignoreList":[],"sources":["../../../../packages/dynamic-forms-ionic/src/lib/fields/button/ionic-button.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/checkbox/ionic-checkbox.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/datepicker/ionic-datepicker.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/input/ionic-input.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/multi-checkbox/ionic-multi-checkbox.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/radio/ionic-radio.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/select/ionic-select.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/slider/ionic-slider.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/textarea/ionic-textarea.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/toggle/ionic-toggle-control.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/toggle/ionic-toggle.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/types/types.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/button/ionic-button.mapper.ts","../../../../packages/dynamic-forms-ionic/src/lib/config/ionic-field-config.ts","../../../../packages/dynamic-forms-ionic/src/lib/providers/ionic-providers.ts","../../../../packages/dynamic-forms-ionic/src/lib/addons/ion-button-addon.component.ts","../../../../packages/dynamic-forms-ionic/src/lib/addons/ion-icon-addon.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { IonButton } from '@ionic/angular/standalone';\nimport { AsyncPipe } from '@angular/common';\nimport { FormEvent } from '@ng-forge/dynamic-forms';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/integration';\nimport { injectNgForgeAction, NgForgeActionHost } from '@ng-forge/dynamic-forms/integration';\nimport { IonicButtonProps } from './ionic-button.type';\n\n@Component({\n selector: 'df-ion-button',\n imports: [IonButton, DynamicTextPipe, AsyncPipe],\n hostDirectives: [NgForgeActionHost],\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n template: `\n @let buttonId = action.key() + '-button';\n\n <ion-button\n [id]=\"buttonId\"\n [type]=\"buttonType()\"\n [expand]=\"props()?.expand\"\n [fill]=\"props()?.fill || 'solid'\"\n [shape]=\"props()?.shape\"\n [size]=\"props()?.size\"\n [color]=\"props()?.color || 'primary'\"\n [strong]=\"props()?.strong\"\n [disabled]=\"action.disabled()\"\n [attr.tabindex]=\"action.tabIndex()\"\n [attr.data-testid]=\"buttonTestId()\"\n (click)=\"onClick()\"\n >\n {{ action.label() | dynamicText | async }}\n </ion-button>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class IonicButtonFieldComponent<TEvent extends FormEvent> {\n protected readonly action = injectNgForgeAction<TEvent>();\n\n readonly props = input<IonicButtonProps>();\n\n readonly buttonType = computed(() => this.props()?.type ?? 'button');\n\n readonly buttonTestId = computed(() => `${this.buttonType()}-${this.action.key()}`);\n\n onClick(): void {\n if (this.buttonType() === 'submit') return;\n this.action.dispatch();\n }\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { IonCheckbox, IonNote } from '@ionic/angular/standalone';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/integration';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { IonicCheckboxProps } from './ionic-checkbox.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-ion-checkbox',\n imports: [IonCheckbox, IonNote, FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field();\n @let checkboxId = ngf.key() + '-checkbox';\n\n <ion-checkbox\n ngForgeControl\n [id]=\"checkboxId\"\n [formField]=\"f\"\n [labelPlacement]=\"props()?.labelPlacement ?? 'end'\"\n [justify]=\"props()?.justify\"\n [color]=\"props()?.color ?? 'primary'\"\n [indeterminate]=\"props()?.indeterminate ?? false\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n >\n {{ ngf.label() | dynamicText | async }}\n </ion-checkbox>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <ion-note color=\"danger\" class=\"df-ion-error\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</ion-note>\n } @else if (props()?.hint; as hint) {\n <ion-note class=\"df-ion-hint\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</ion-note>\n }\n `,\n styleUrl: '../../styles/_form-field.scss',\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class IonicCheckboxFieldComponent {\n protected readonly ngf = injectNgForgeField<boolean>();\n\n readonly props = input<IonicCheckboxProps>();\n}\n","import { ChangeDetectionStrategy, Component, input, signal } from '@angular/core';\nimport {\n IonButton,\n IonButtons,\n IonContent,\n IonDatetime,\n IonHeader,\n IonInput,\n IonModal,\n IonNote,\n IonTitle,\n IonToolbar,\n} from '@ionic/angular/standalone';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/integration';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { IonicDatepickerProps } from './ionic-datepicker.type';\nimport { AsyncPipe } from '@angular/common';\nimport { format } from 'date-fns';\n\n@Component({\n selector: 'df-ion-datepicker',\n imports: [\n IonInput,\n IonModal,\n IonDatetime,\n IonNote,\n IonButtons,\n IonHeader,\n IonContent,\n IonToolbar,\n IonTitle,\n IonButton,\n DynamicTextPipe,\n AsyncPipe,\n NgForgeControl,\n ],\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field();\n @let dateValue = f().value();\n @let inputId = ngf.key() + '-input';\n\n <ion-input\n ngForgeControl\n [id]=\"inputId\"\n [label]=\"(ngf.label() | dynamicText | async) ?? undefined\"\n [labelPlacement]=\"'stacked'\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [disabled]=\"f().disabled()\"\n [value]=\"formatDisplayDate(dateValue)\"\n [readonly]=\"true\"\n [fill]=\"'outline'\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n (click)=\"!f().disabled() && openModal()\"\n />\n @if (ngf.errorsToDisplay()[0]; as error) {\n <ion-note color=\"danger\" class=\"df-ion-error\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</ion-note>\n } @else if (props()?.hint; as hint) {\n <ion-note class=\"df-ion-hint\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</ion-note>\n }\n\n <ion-modal [isOpen]=\"isModalOpen()\" (didDismiss)=\"closeModal()\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-title>{{ ngf.label() | dynamicText | async }}</ion-title>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"closeModal()\">Close</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content>\n <ion-datetime\n [presentation]=\"props()?.presentation ?? 'date'\"\n [value]=\"dateToIsoString(dateValue)\"\n [multiple]=\"props()?.multiple ?? false\"\n [preferWheel]=\"props()?.preferWheel ?? false\"\n [showDefaultButtons]=\"props()?.showDefaultButtons ?? false\"\n [showDefaultTitle]=\"props()?.showDefaultTitle ?? false\"\n [showDefaultTimeLabel]=\"props()?.showDefaultTimeLabel ?? true\"\n [showClearButton]=\"props()?.showClearButton ?? false\"\n [color]=\"props()?.color\"\n [min]=\"dateToIsoString(minDate())\"\n [max]=\"dateToIsoString(maxDate())\"\n (ionChange)=\"onDateChange($event)\"\n >\n </ion-datetime>\n </ion-content>\n </ng-template>\n </ion-modal>\n `,\n styleUrl: '../../styles/_form-field.scss',\n styles: [\n `\n ion-input {\n cursor: pointer;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class IonicDatepickerFieldComponent {\n protected readonly ngf = injectNgForgeField<Date | null>();\n\n readonly minDate = input<Date | null>(null);\n readonly maxDate = input<Date | null>(null);\n readonly startAt = input<Date | null>(null);\n readonly props = input<IonicDatepickerProps>();\n\n readonly isModalOpen = signal(false);\n\n openModal() {\n this.isModalOpen.set(true);\n }\n\n closeModal() {\n this.isModalOpen.set(false);\n }\n\n onDateChange(event: CustomEvent) {\n const value = event.detail.value;\n // ion-datetime emits ISO 8601 strings internally; convert to Date | null\n // to match the field tree's value type.\n if (value && typeof value === 'string' && value.length > 0) {\n const date = new Date(value);\n this.ngf.field()().value.set(date);\n } else {\n this.ngf.field()().value.set(null);\n }\n this.closeModal();\n }\n\n dateToIsoString(date: Date | null | undefined): string | undefined {\n if (!date) return undefined;\n return date.toISOString();\n }\n\n formatDisplayDate(date: Date | null | undefined): string {\n if (!date) return '';\n\n const presentation = this.props()?.presentation ?? 'date';\n\n switch (presentation) {\n case 'date':\n return format(date, 'MMM d, yyyy');\n case 'date-time':\n case 'time-date':\n return format(date, 'MMM d, yyyy, h:mm a');\n case 'time':\n return format(date, 'h:mm a');\n case 'month':\n return format(date, 'MMMM yyyy');\n case 'month-year':\n return format(date, 'MMM yyyy');\n case 'year':\n return format(date, 'yyyy');\n default:\n return format(date, 'MMM d, yyyy');\n }\n }\n}\n","import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, DestroyRef, ElementRef, forwardRef, inject, input, signal } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { IonInput, IonNote } from '@ionic/angular/standalone';\nimport { AddonActionContext, AddonActionPreset, DynamicFormLogger } from '@ng-forge/dynamic-forms';\nimport { DfAddonSlot } from '@ng-forge/dynamic-forms/integration';\nimport { WrapperFieldInputs } from '@ng-forge/dynamic-forms/integration';\nimport { DynamicTextPipe, FIELD_SIGNAL_CONTEXT } from '@ng-forge/dynamic-forms/integration';\nimport {\n ADDON_PRESET_HANDLER,\n AddonPresetHandler,\n injectNgForgeAddons,\n injectNgForgeField,\n NgForgeAddons,\n NgForgeControl,\n NgForgeFieldHost,\n} from '@ng-forge/dynamic-forms/integration';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport {\n IONIC_CONFIG,\n IONIC_INPUT_TYPE_OVERRIDE,\n IonicInlineButtonAddonComponent,\n runIonicPresetAction,\n} from '@ng-forge/dynamic-forms-ionic/shared';\nimport { IonicInputAddon, IonicInputProps } from './ionic-input.type';\n\n// minlength/maxlength bindings: Signal Forms auto-syncs these on NATIVE\n// inputs; <ion-input> is a Stencil web component so we bind directly from\n// FieldState (`f().maxLength?.()` — the signal itself is missing when no\n// validator is configured).\n@Component({\n selector: 'df-ion-input',\n // IonButton intentionally NOT imported — it would collide with\n // IonicInlineButtonAddonComponent on `<ion-button>` (NG0300).\n imports: [IonInput, IonNote, FormField, DynamicTextPipe, AsyncPipe, NgForgeControl, DfAddonSlot, IonicInlineButtonAddonComponent],\n hostDirectives: [NgForgeFieldHost, NgForgeAddons],\n template: `\n @let f = ngf.field();\n @let inputId = ngf.key() + '-input';\n\n <ion-input\n ngForgeControl\n [id]=\"inputId\"\n [type]=\"type()\"\n [formField]=\"f\"\n [label]=\"(ngf.label() | dynamicText | async) ?? undefined\"\n [labelPlacement]=\"labelPlacement()\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [clearInput]=\"props()?.clearInput ?? false\"\n [counter]=\"props()?.counter ?? false\"\n [minlength]=\"f().minLength?.()\"\n [maxlength]=\"f().maxLength?.()\"\n [color]=\"color()\"\n [fill]=\"fill()\"\n [shape]=\"shape()\"\n [readonly]=\"f().readonly()\"\n [helperText]=\"ngf.errorsToDisplay().length === 0 ? ((props()?.hint | dynamicText | async) ?? undefined) : undefined\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n >\n @for (a of decorativePrefixAddons(); track $index) {\n <span slot=\"start\">\n <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n </span>\n }\n @for (a of buttonPrefixAddons(); track $index) {\n <ion-button df-ion-button-addon slot=\"start\" [addon]=\"a\" [fieldInputs]=\"fieldInputs()\"></ion-button>\n }\n @for (a of buttonSuffixAddons(); track $index) {\n <ion-button df-ion-button-addon slot=\"end\" [addon]=\"a\" [fieldInputs]=\"fieldInputs()\"></ion-button>\n }\n @for (a of decorativeSuffixAddons(); track $index) {\n <span slot=\"end\">\n <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n </span>\n }\n </ion-input>\n @if (ngf.errorsToDisplay()[0]; as error) {\n <ion-note color=\"danger\" class=\"df-ion-error\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</ion-note>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n styleUrl: '../../styles/_form-field.scss',\n providers: [\n {\n provide: IONIC_INPUT_TYPE_OVERRIDE,\n useFactory: () => signal<string | undefined>(undefined),\n },\n {\n // Adapter-specific preset semantics for `ion-button` addons (clear /\n // reset / paste / copy / toggle-password-visibility). The directive\n // (`NgForgeAddonAction`) delegates here when an addon configures a\n // `preset`. Per-ion-input-instance so the `typeOverride` signal is\n // scoped to one field.\n provide: ADDON_PRESET_HANDLER,\n useFactory: (): AddonPresetHandler => {\n const typeOverride = inject(IONIC_INPUT_TYPE_OVERRIDE);\n const fsc = inject(FIELD_SIGNAL_CONTEXT, { optional: true });\n const logger = inject(DynamicFormLogger);\n // forwardRef for baselineType only — host.props()?.type gates toggle-password-visibility.\n const host = inject(forwardRef(() => IonicInputFieldComponent));\n return {\n run: (preset: string, ctx: AddonActionContext) => {\n const fieldKey = ctx.field.key;\n return runIonicPresetAction(preset as AddonActionPreset, ctx, {\n typeOverride,\n fieldValueSetter: ctx.setValue,\n fieldDefaultValueGetter:\n fsc && fieldKey ? () => (fsc.defaultValues() as Record<string, unknown> | undefined)?.[fieldKey] : undefined,\n baselineType: () => host.props()?.type,\n logger,\n });\n },\n };\n },\n },\n ],\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n /* Per-side padding knobs on each slot wrapper (independent prefix/suffix). */\n :host {\n --df-ion-addon-prefix-outer-padding: 0;\n --df-ion-addon-prefix-inner-padding: 0.5rem;\n --df-ion-addon-suffix-inner-padding: 0.5rem;\n --df-ion-addon-suffix-outer-padding: 0;\n }\n /* inline-flex on slot wrappers prevents baseline-pinning of decorative addon glyphs. */\n :host ::ng-deep ion-input [slot='start'],\n :host ::ng-deep ion-input [slot='end'] {\n display: inline-flex;\n align-items: center;\n align-self: center;\n line-height: 1;\n }\n :host ::ng-deep ion-input [slot='start'] df-addon-slot,\n :host ::ng-deep ion-input [slot='end'] df-addon-slot,\n :host ::ng-deep ion-input [slot='start'] df-ion-icon-addon,\n :host ::ng-deep ion-input [slot='end'] df-ion-icon-addon {\n display: inline-flex;\n align-items: center;\n line-height: 1;\n }\n :host ::ng-deep ion-input [slot='start'] {\n padding-inline-start: var(--df-ion-addon-prefix-outer-padding);\n padding-inline-end: var(--df-ion-addon-prefix-inner-padding);\n }\n :host ::ng-deep ion-input [slot='end'] {\n padding-inline-start: var(--df-ion-addon-suffix-inner-padding);\n padding-inline-end: var(--df-ion-addon-suffix-outer-padding);\n }\n /* Inherit input text color so icons stay readable on dark themes\n (Ionic's default \"medium\" greys out and fails WCAG on dark inputs). */\n :host ::ng-deep ion-input ion-icon {\n color: inherit;\n }\n `,\n ],\n})\nexport default class IonicInputFieldComponent {\n private readonly elementRef = inject(ElementRef<HTMLElement>);\n private ionicConfig = inject(IONIC_CONFIG, { optional: true });\n\n protected readonly ngf = injectNgForgeField<string>();\n protected readonly ngfa = injectNgForgeAddons<IonicInputAddon>();\n\n readonly props = input<IonicInputProps>();\n\n /**\n * Wrapper-style host bag pushed by `DfFieldOutlet`. Declared at the\n * component level so `setInputIfDeclared` (which uses\n * `reflectComponentType`) can write it.\n */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n\n /** Per-instance type override populated by `toggle-password-visibility` preset. */\n private readonly typeOverride = inject(IONIC_INPUT_TYPE_OVERRIDE);\n\n protected readonly fill = computed(() => this.props()?.fill ?? this.ionicConfig?.fill ?? 'solid');\n protected readonly shape = computed(() => this.props()?.shape ?? this.ionicConfig?.shape);\n /** Bootstrap / PrimeNG. Consumers can opt into Ionic's native inline 'start' */\n protected readonly labelPlacement = computed(() => this.props()?.labelPlacement ?? this.ionicConfig?.labelPlacement ?? 'stacked');\n protected readonly color = computed(() => this.props()?.color ?? this.ionicConfig?.color);\n\n /** Override (set by `toggle-password-visibility` preset) wins over `props().type`. */\n protected readonly type = computed(() => this.typeOverride() ?? this.props()?.type ?? 'text');\n\n /** Per-type split: ion-button addons render inline via the attribute-\n * selector inline component (so the slotted element is a native\n * <ion-button> Ionic can style); everything else (icon/text/template/\n * component types) goes through the universal <df-addon-slot> dispatcher\n * wrapped in <span slot=\"start|end\"> for safe shadow-DOM projection. */\n protected readonly buttonPrefixAddons = computed(() => this.ngfa.prefixAddons().filter((a) => a.type === 'ion-button'));\n protected readonly buttonSuffixAddons = computed(() => this.ngfa.suffixAddons().filter((a) => a.type === 'ion-button'));\n protected readonly decorativePrefixAddons = computed(() => this.ngfa.prefixAddons().filter((a) => a.type !== 'ion-button'));\n protected readonly decorativeSuffixAddons = computed(() => this.ngfa.suffixAddons().filter((a) => a.type !== 'ion-button'));\n\n /** Set when the component is destroyed — guards async aria-describedby sync against teardown. */\n private destroyed = false;\n\n constructor() {\n inject(DestroyRef).onDestroy(() => (this.destroyed = true));\n // ion-input encapsulates a native <input> in shadow DOM and does not automatically\n // propagate aria-describedby to it. This effect imperatively syncs the attribute\n // after a microtask to ensure Ionic has resolved the internal element.\n explicitEffect([this.ngf.ariaDescribedBy], ([describedBy]) => {\n queueMicrotask(() => {\n if (this.destroyed) return;\n const ionInput = this.elementRef.nativeElement.querySelector('ion-input') as HTMLIonInputElement | null;\n if (ionInput?.getInputElement) {\n ionInput.getInputElement().then((inputEl) => {\n if (this.destroyed || !inputEl) return;\n if (describedBy) {\n inputEl.setAttribute('aria-describedby', describedBy);\n } else {\n inputEl.removeAttribute('aria-describedby');\n }\n });\n }\n });\n });\n }\n}\n","import { ChangeDetectionStrategy, Component, computed, input, linkedSignal } from '@angular/core';\nimport { IonCheckbox, IonItem, IonNote } from '@ionic/angular/standalone';\nimport { FieldOption, ValueType } from '@ng-forge/dynamic-forms';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/integration';\nimport { injectNgForgeField, NgForgeFieldHost, isEqual, NgForgeControl } from '@ng-forge/dynamic-forms/integration';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { IonicMultiCheckboxProps } from './ionic-multi-checkbox.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-ion-multi-checkbox',\n imports: [IonCheckbox, IonItem, IonNote, DynamicTextPipe, AsyncPipe, NgForgeControl],\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field();\n @let checked = checkedValuesMap();\n @if (ngf.label(); as label) {\n <div class=\"checkbox-group-label\">{{ label | dynamicText | async }}</div>\n }\n\n <div\n class=\"checkbox-group\"\n role=\"group\"\n [attr.aria-invalid]=\"ngf.ariaInvalid()\"\n [attr.aria-required]=\"ngf.ariaRequired()\"\n [attr.aria-describedby]=\"ngf.ariaDescribedBy()\"\n [class.ion-invalid]=\"ngf.showErrors()\"\n [class.ion-touched]=\"f().touched()\"\n >\n @for (option of options(); track option.value) {\n <ion-item lines=\"none\">\n <ion-checkbox\n ngForgeControl\n [checked]=\"checked['' + option.value]\"\n [disabled]=\"f().disabled() || option.disabled\"\n [labelPlacement]=\"props()?.labelPlacement ?? 'end'\"\n [justify]=\"props()?.justify ?? 'start'\"\n [color]=\"props()?.color ?? 'primary'\"\n (ionChange)=\"onCheckboxChange(option, $event.detail.checked)\"\n >\n {{ option.label | dynamicText | async }}\n </ion-checkbox>\n </ion-item>\n }\n </div>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <ion-note color=\"danger\" class=\"df-ion-error\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</ion-note>\n } @else if (props()?.hint; as hint) {\n <ion-note class=\"df-ion-hint\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</ion-note>\n }\n `,\n styleUrl: '../../styles/_form-field.scss',\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n .checkbox-group-label {\n margin-bottom: 8px;\n font-weight: 500;\n }\n\n .checkbox-group {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n ion-item {\n --padding-start: 0;\n --inner-padding-end: 0;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class IonicMultiCheckboxFieldComponent {\n protected readonly ngf = injectNgForgeField<ValueType[]>();\n\n readonly options = input<FieldOption<ValueType>[]>([]);\n readonly props = input<IonicMultiCheckboxProps>();\n\n valueViewModel = linkedSignal<FieldOption<ValueType>[]>(\n () => {\n const currentValues = this.ngf.field()().value();\n return this.options().filter((option) => currentValues.includes(option.value));\n },\n { equal: isEqual },\n );\n\n /** Computed map of checked option values for O(1) lookup in template */\n readonly checkedValuesMap = computed(() => {\n const map: Record<string, boolean> = {};\n for (const opt of this.valueViewModel()) {\n map[String(opt.value)] = true;\n }\n return map;\n });\n\n constructor() {\n explicitEffect([this.valueViewModel], ([selectedOptions]) => {\n const selectedValues = selectedOptions.map((option) => option.value);\n\n if (!isEqual(selectedValues, this.ngf.field()().value())) {\n this.ngf.field()().value.set(selectedValues);\n }\n });\n\n explicitEffect([this.options], ([options]) => {\n const values = options.map((option) => option.value);\n const uniqueValues = new Set(values);\n\n if (values.length !== uniqueValues.size) {\n const duplicates = values.filter((value, index) => values.indexOf(value) !== index);\n throw new Error(`Duplicate option values detected in ionic-multi-checkbox: ${duplicates.join(', ')}`);\n }\n });\n }\n\n onCheckboxChange(option: FieldOption<ValueType>, checked: boolean): void {\n this.valueViewModel.update((currentOptions) => {\n if (checked) {\n return currentOptions.some((opt) => opt.value === option.value) ? currentOptions : [...currentOptions, option];\n } else {\n return currentOptions.filter((opt) => opt.value !== option.value);\n }\n });\n }\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { IonItem, IonNote, IonRadio, IonRadioGroup } from '@ionic/angular/standalone';\nimport { FieldOption, ValueType } from '@ng-forge/dynamic-forms';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/integration';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { IonicRadioProps } from './ionic-radio.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-ion-radio',\n imports: [IonRadioGroup, IonRadio, IonItem, IonNote, FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field();\n @let radioGroupId = ngf.key() + '-radio-group';\n @if (ngf.label(); as label) {\n <div class=\"radio-label\">{{ label | dynamicText | async }}</div>\n }\n\n <ion-radio-group\n [id]=\"radioGroupId\"\n [formField]=\"f\"\n [compareWith]=\"props()?.compareWith || defaultCompare\"\n [attr.aria-invalid]=\"ngf.ariaInvalid()\"\n [attr.aria-required]=\"ngf.ariaRequired()\"\n [attr.aria-describedby]=\"ngf.ariaDescribedBy()\"\n >\n @for (option of options(); track option.value) {\n <ion-item [lines]=\"'none'\">\n <ion-radio\n ngForgeControl\n [value]=\"option.value\"\n [disabled]=\"option.disabled || false\"\n [labelPlacement]=\"props()?.labelPlacement ?? 'end'\"\n [justify]=\"props()?.justify\"\n [color]=\"props()?.color ?? 'primary'\"\n >\n {{ option.label | dynamicText | async }}\n </ion-radio>\n </ion-item>\n }\n </ion-radio-group>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <ion-note color=\"danger\" class=\"df-ion-error\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</ion-note>\n } @else if (props()?.hint; as hint) {\n <ion-note class=\"df-ion-hint\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</ion-note>\n }\n `,\n styleUrl: '../../styles/_form-field.scss',\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n .radio-label {\n font-size: 0.875rem;\n font-weight: 500;\n margin-bottom: 0.5rem;\n color: var(--ion-text-color);\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class IonicRadioFieldComponent {\n protected readonly ngf = injectNgForgeField<ValueType>();\n\n readonly options = input<FieldOption<ValueType>[]>([]);\n readonly props = input<IonicRadioProps>();\n\n defaultCompare = Object.is;\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { IonNote, IonSelect, IonSelectOption } from '@ionic/angular/standalone';\nimport { FieldOption, ValueType } from '@ng-forge/dynamic-forms';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/integration';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { IonicSelectProps } from './ionic-select.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-ion-select',\n imports: [IonSelect, IonSelectOption, IonNote, FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field();\n @let selectId = ngf.key() + '-select';\n\n <ion-select\n ngForgeControl\n [id]=\"selectId\"\n [formField]=\"f\"\n [label]=\"(ngf.label() | dynamicText | async) ?? undefined\"\n [labelPlacement]=\"props()?.labelPlacement ?? 'stacked'\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [multiple]=\"props()?.multiple ?? false\"\n [compareWith]=\"props()?.compareWith ?? defaultCompare\"\n [interface]=\"props()?.interface ?? 'alert'\"\n [interfaceOptions]=\"props()?.interfaceOptions ?? {}\"\n [cancelText]=\"props()?.cancelText ?? 'Cancel'\"\n [okText]=\"props()?.okText ?? 'OK'\"\n [color]=\"props()?.color\"\n [fill]=\"props()?.fill ?? 'outline'\"\n [shape]=\"props()?.shape\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n >\n @for (option of options(); track option.value) {\n <ion-select-option [value]=\"option.value\" [disabled]=\"option.disabled || false\">\n {{ option.label | dynamicText | async }}\n </ion-select-option>\n }\n </ion-select>\n @if (ngf.errorsToDisplay()[0]; as error) {\n <ion-note color=\"danger\" class=\"df-ion-error\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</ion-note>\n } @else if (props()?.hint; as hint) {\n <ion-note class=\"df-ion-hint\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</ion-note>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n styleUrl: '../../styles/_form-field.scss',\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n})\nexport default class IonicSelectFieldComponent {\n protected readonly ngf = injectNgForgeField<ValueType>();\n\n readonly options = input<FieldOption<ValueType>[]>([]);\n readonly props = input<IonicSelectProps>();\n\n defaultCompare = Object.is;\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { IonNote, IonRange } from '@ionic/angular/standalone';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/integration';\nimport { NgForgeHostControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { IonicSliderProps } from './ionic-slider.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-ion-slider',\n imports: [IonRange, IonNote, FormField, DynamicTextPipe, AsyncPipe],\n hostDirectives: [NgForgeFieldHost, NgForgeHostControl],\n template: `\n @let f = ngf.field();\n @let inputId = ngf.key() + '-input';\n\n <ion-range\n [id]=\"inputId\"\n [formField]=\"f\"\n [label]=\"(ngf.label() | dynamicText | async) ?? undefined\"\n [labelPlacement]=\"props()?.labelPlacement ?? 'stacked'\"\n [min]=\"f().min?.() ?? props()?.min ?? 0\"\n [max]=\"f().max?.() ?? props()?.max ?? 100\"\n [step]=\"step() ?? props()?.step ?? 1\"\n [dualKnobs]=\"props()?.dualKnobs ?? false\"\n [pin]=\"props()?.pin ?? false\"\n [pinFormatter]=\"props()?.pinFormatter ?? defaultPinFormatter\"\n [ticks]=\"props()?.ticks ?? false\"\n [snaps]=\"props()?.snaps ?? false\"\n [color]=\"props()?.color ?? 'primary'\"\n />\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <ion-note color=\"danger\" class=\"df-ion-error\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</ion-note>\n } @else if (props()?.hint; as hint) {\n <ion-note class=\"df-ion-hint\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</ion-note>\n }\n `,\n styleUrl: '../../styles/_form-field.scss',\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class IonicSliderFieldComponent {\n protected readonly ngf = injectNgForgeField<number>();\n\n readonly step = input<number>();\n readonly props = input<IonicSliderProps>();\n\n protected defaultPinFormatter = (value: number) => String(value);\n}\n","import { ChangeDetectionStrategy, Component, ElementRef, inject, input } from '@angular/core';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { FormField } from '@angular/forms/signals';\nimport { IonNote, IonTextarea } from '@ionic/angular/standalone';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/integration';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { IonicTextareaProps } from './ionic-textarea.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-ion-textarea',\n imports: [IonTextarea, IonNote, FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field();\n @let textareaId = ngf.key() + '-textarea';\n\n <ion-textarea\n ngForgeControl\n [id]=\"textareaId\"\n [formField]=\"f\"\n [label]=\"(ngf.label() | dynamicText | async) ?? undefined\"\n [labelPlacement]=\"props()?.labelPlacement ?? 'stacked'\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [rows]=\"props()?.rows ?? 4\"\n [autoGrow]=\"props()?.autoGrow ?? false\"\n [counter]=\"props()?.counter ?? false\"\n [minlength]=\"f().minLength?.()\"\n [maxlength]=\"f().maxLength?.()\"\n [color]=\"props()?.color\"\n [fill]=\"props()?.fill ?? 'outline'\"\n [shape]=\"props()?.shape\"\n [readonly]=\"f().readonly()\"\n [helperText]=\"ngf.errorsToDisplay().length === 0 ? ((props()?.hint | dynamicText | async) ?? undefined) : undefined\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n />\n @if (ngf.errorsToDisplay()[0]; as error) {\n <ion-note color=\"danger\" class=\"df-ion-error\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</ion-note>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n styleUrl: '../../styles/_form-field.scss',\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n})\nexport default class IonicTextareaFieldComponent {\n private readonly elementRef = inject(ElementRef<HTMLElement>);\n\n protected readonly ngf = injectNgForgeField<string>();\n\n readonly props = input<IonicTextareaProps>();\n\n constructor() {\n // ion-textarea encapsulates a native <textarea> in shadow DOM and does not automatically\n // propagate aria-describedby to it. This effect imperatively syncs the attribute\n // after a microtask to ensure Ionic has resolved the internal element.\n explicitEffect([this.ngf.ariaDescribedBy], ([describedBy]) => {\n queueMicrotask(() => {\n const ionTextarea = this.elementRef.nativeElement.querySelector('ion-textarea') as HTMLIonTextareaElement | null;\n if (ionTextarea?.getInputElement) {\n ionTextarea.getInputElement().then((textareaEl) => {\n if (!textareaEl) return;\n if (describedBy) {\n textareaEl.setAttribute('aria-describedby', describedBy);\n } else {\n textareaEl.removeAttribute('aria-describedby');\n }\n });\n }\n });\n });\n }\n}\n","import { ChangeDetectionStrategy, Component, computed, input, model } from '@angular/core';\nimport type { FormCheckboxControl } from '@angular/forms/signals';\nimport { IonToggle } from '@ionic/angular/standalone';\nimport { NgForgeControl } from '@ng-forge/dynamic-forms/integration';\n\n/**\n * ion-toggle wrapper implementing FormCheckboxControl. Rendered inside\n * `df-ion-toggle`. `NgForgeControl` on `<ion-toggle>` claims the ambient\n * parent NgForgeField and routes meta + aria onto that element.\n */\n@Component({\n selector: 'df-ion-toggle-control',\n imports: [IonToggle, NgForgeControl],\n template: `\n <ion-toggle\n ngForgeControl\n [checked]=\"isChecked()\"\n (ionChange)=\"onToggleChange($event)\"\n (ionBlur)=\"onBlur()\"\n [labelPlacement]=\"labelPlacement()\"\n [justify]=\"justify()\"\n [color]=\"color()\"\n [enableOnOffLabels]=\"enableOnOffLabels()\"\n [disabled]=\"isEffectivelyDisabled()\"\n [attr.tabindex]=\"tabIndex()\"\n [attr.aria-readonly]=\"ariaReadonly()\"\n >\n <ng-content />\n </ion-toggle>\n `,\n styleUrl: '../../styles/_form-field.scss',\n host: {\n style: 'display: block',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class IonicToggleControlComponent implements FormCheckboxControl {\n // ─────────────────────────────────────────────────────────────────────────────\n // FormCheckboxControl implementation\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** The checked state - required by FormCheckboxControl */\n readonly checked = model<boolean>(false);\n\n /** Tracks whether the field has been touched - used by Field directive */\n readonly touched = model<boolean>(false);\n\n /** Whether the field is disabled */\n readonly disabled = input<boolean>(false);\n\n /** Whether the field is readonly */\n readonly readonly = input<boolean>(false);\n\n /** Whether the field is invalid (from Field directive) */\n readonly invalid = input<boolean>(false);\n\n /** Whether the field is required (from Field directive) */\n readonly required = input<boolean>(false);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Ionic-specific props\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly labelPlacement = input<'start' | 'end' | 'fixed' | 'stacked'>('end');\n readonly justify = input<'start' | 'end' | 'space-between' | undefined>(undefined);\n readonly color = input<string>('primary');\n readonly enableOnOffLabels = input<boolean>(false);\n readonly tabIndex = input<number | undefined>(undefined);\n\n // aria-invalid / aria-required / aria-describedby are written to <ion-toggle>\n // by NgForgeControl. aria-readonly is Ionic-specific and stays template-side.\n protected readonly ariaReadonly = computed(() => (this.readonly() ? true : null));\n\n /** Computed checked state - ensures proper boolean conversion for ion-toggle */\n protected readonly isChecked = computed(() => {\n return this.checked() === true;\n });\n\n /**\n * ion-toggle doesn't have a native readonly attribute.\n * When readonly, we disable the toggle to prevent changes while maintaining the visual state.\n */\n protected readonly isEffectivelyDisabled = computed(() => {\n return this.disabled() || this.readonly();\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Event Handlers\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Handle toggle change - sync ion-toggle's checked state to our checked model */\n onToggleChange(event: CustomEvent<{ checked: boolean; value: string }>): void {\n this.checked.set(event.detail.checked);\n }\n\n /** Marks the field as touched when toggle loses focus */\n onBlur(): void {\n this.touched.set(true);\n }\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { IonNote } from '@ionic/angular/standalone';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/integration';\nimport { injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { IonicToggleProps } from './ionic-toggle.type';\nimport { IonicToggleControlComponent } from './ionic-toggle-control.component';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-ion-toggle',\n imports: [IonicToggleControlComponent, IonNote, FormField, DynamicTextPipe, AsyncPipe],\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field();\n @let toggleId = ngf.key() + '-toggle';\n\n <df-ion-toggle-control\n [id]=\"toggleId\"\n [formField]=\"f\"\n [labelPlacement]=\"props()?.labelPlacement ?? 'end'\"\n [justify]=\"props()?.justify\"\n [color]=\"props()?.color ?? 'primary'\"\n [enableOnOffLabels]=\"props()?.enableOnOffLabels ?? false\"\n [tabIndex]=\"ngf.tabIndex()\"\n >\n {{ ngf.label() | dynamicText | async }}\n </df-ion-toggle-control>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <ion-note color=\"danger\" class=\"df-ion-error\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</ion-note>\n } @else if (props()?.hint; as hint) {\n <ion-note class=\"df-ion-hint\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</ion-note>\n }\n `,\n styleUrl: '../../styles/_form-field.scss',\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class IonicToggleFieldComponent {\n protected readonly ngf = injectNgForgeField<boolean>();\n\n readonly props = input<IonicToggleProps>();\n}\n","/**\n * Ionic field type constants\n * Based on available field components in the /fields folder\n */\nexport const IonicField = {\n Input: 'input',\n Select: 'select',\n Checkbox: 'checkbox',\n Button: 'button',\n Submit: 'submit',\n Next: 'next',\n Previous: 'previous',\n AddArrayItem: 'add-array-item',\n PrependArrayItem: 'prepend-array-item',\n InsertArrayItem: 'insert-array-item',\n RemoveArrayItem: 'remove-array-item',\n PopArrayItem: 'pop-array-item',\n ShiftArrayItem: 'shift-array-item',\n Textarea: 'textarea',\n Radio: 'radio',\n MultiCheckbox: 'multi-checkbox',\n Datepicker: 'datepicker',\n Slider: 'slider',\n Toggle: 'toggle',\n} as const;\n\nexport type IonicFieldType = (typeof IonicField)[keyof typeof IonicField];\n","import { computed, inject, isSignal, Signal } from '@angular/core';\nimport { FieldDef } from '@ng-forge/dynamic-forms';\nimport { ARRAY_CONTEXT, buildBaseInputs, DEFAULT_PROPS, injectNonFieldLogicResolver } from '@ng-forge/dynamic-forms/integration';\n\n/**\n * Generic button mapper for custom events or basic buttons.\n * For specific button types (submit, next, prev, add/remove array items),\n * use the dedicated field types and their specific mappers.\n *\n * @param fieldDef The button field definition\n * @returns Signal containing Record of input names to values for ngComponentOutlet\n */\nexport function buttonFieldMapper(fieldDef: FieldDef<Record<string, unknown>>): Signal<Record<string, unknown>> {\n const defaultProps = inject(DEFAULT_PROPS);\n const arrayContext = inject(ARRAY_CONTEXT, { optional: true });\n const resolveLogic = injectNonFieldLogicResolver(fieldDef);\n\n return computed(() => {\n const baseInputs = buildBaseInputs(fieldDef, defaultProps());\n\n const inputs: Record<string, unknown> = {\n ...baseInputs,\n ...resolveLogic(),\n };\n\n // Add event binding for button events\n if ('event' in fieldDef && fieldDef.event !== undefined) {\n inputs['event'] = fieldDef.event;\n }\n\n // Add eventArgs binding if provided\n if ('eventArgs' in fieldDef && fieldDef.eventArgs !== undefined) {\n inputs['eventArgs'] = fieldDef.eventArgs;\n }\n\n // Add eventContext for token resolution (supports $template, $arrayKey, $index, etc.)\n const template = 'template' in fieldDef ? fieldDef.template : undefined;\n if (template || arrayContext) {\n // Read signal value if index is a signal (supports differential updates)\n const getIndex = () => {\n if (!arrayContext) return -1;\n return isSignal(arrayContext.index) ? arrayContext.index() : arrayContext.index;\n };\n\n inputs['eventContext'] = {\n key: fieldDef.key,\n index: getIndex(),\n arrayKey: arrayContext?.arrayKey ?? '',\n get formValue() {\n return arrayContext?.formValue ?? {};\n },\n template,\n };\n }\n\n return inputs;\n });\n}\n","/* eslint-disable @nx/enforce-module-boundaries -- Published secondary-entry imports must remain package specifiers for real lazy chunks. */\nimport { FieldTypeDefinition } from '@ng-forge/dynamic-forms/integration';\nimport {\n addArrayItemButtonMapper,\n checkboxFieldMapper,\n datepickerFieldMapper,\n insertArrayItemButtonMapper,\n optionsFieldMapper,\n popArrayItemButtonMapper,\n prependArrayItemButtonMapper,\n removeArrayItemButtonMapper,\n shiftArrayItemButtonMapper,\n valueFieldMapper,\n} from '@ng-forge/dynamic-forms/integration';\nimport { IonicField } from '../types/types';\nimport { buttonFieldMapper } from '../fields/button/ionic-button.mapper';\nimport { nextButtonFieldMapper, previousButtonFieldMapper, submitButtonFieldMapper } from '../fields/button/ionic-specific-button.mapper';\n\nconst VALUE_FIELD_TYPES_BASE = {\n renderReadyWhen: ['field'],\n} as const;\n\nconst BUTTON_FIELD_TYPES_BASE = {\n renderReadyWhen: [],\n valueHandling: 'exclude',\n} as const;\n\nconst loadInputComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/input').then(({ IonicInputFieldComponent }) => IonicInputFieldComponent);\nconst loadSelectComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/select').then(({ IonicSelectFieldComponent }) => IonicSelectFieldComponent);\nconst loadCheckboxComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/checkbox').then(({ IonicCheckboxFieldComponent }) => IonicCheckboxFieldComponent);\nconst loadButtonComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/button').then(({ IonicButtonFieldComponent }) => IonicButtonFieldComponent);\nconst loadTextareaComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/textarea').then(({ IonicTextareaFieldComponent }) => IonicTextareaFieldComponent);\nconst loadRadioComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/radio').then(({ IonicRadioFieldComponent }) => IonicRadioFieldComponent);\nconst loadMultiCheckboxComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/multi-checkbox').then(\n ({ IonicMultiCheckboxFieldComponent }) => IonicMultiCheckboxFieldComponent,\n );\nconst loadDatepickerComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/datepicker').then(({ IonicDatepickerFieldComponent }) => IonicDatepickerFieldComponent);\nconst loadSliderComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/slider').then(({ IonicSliderFieldComponent }) => IonicSliderFieldComponent);\nconst loadToggleComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/toggle').then(({ IonicToggleFieldComponent }) => IonicToggleFieldComponent);\n\n/**\n * Ionic field type definitions\n * Follows the FieldTypeDefinition interface for proper registry integration\n */\nexport const IONIC_FIELD_TYPES: FieldTypeDefinition[] = [\n {\n name: IonicField.Input,\n loadComponent: loadInputComponent,\n mapper: valueFieldMapper,\n propsToMeta: ['type'],\n scope: ['text-input', 'numeric'],\n addons: {\n slots: ['prefix', 'suffix'],\n },\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Select,\n loadComponent: loadSelectComponent,\n mapper: optionsFieldMapper,\n scope: 'single-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Checkbox,\n loadComponent: loadCheckboxComponent,\n mapper: checkboxFieldMapper,\n scope: 'boolean',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Button,\n loadComponent: loadButtonComponent,\n mapper: buttonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Submit,\n loadComponent: loadButtonComponent,\n mapper: submitButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Next,\n loadComponent: loadButtonComponent,\n mapper: nextButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Previous,\n loadComponent: loadButtonComponent,\n mapper: previousButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.AddArrayItem,\n loadComponent: loadButtonComponent,\n mapper: addArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.PrependArrayItem,\n loadComponent: loadButtonComponent,\n mapper: prependArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.InsertArrayItem,\n loadComponent: loadButtonComponent,\n mapper: insertArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.RemoveArrayItem,\n loadComponent: loadButtonComponent,\n mapper: removeArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.PopArrayItem,\n loadComponent: loadButtonComponent,\n mapper: popArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.ShiftArrayItem,\n loadComponent: loadButtonComponent,\n mapper: shiftArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Textarea,\n loadComponent: loadTextareaComponent,\n mapper: valueFieldMapper,\n propsToMeta: ['rows'],\n scope: 'text-input',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Radio,\n loadComponent: loadRadioComponent,\n mapper: optionsFieldMapper,\n scope: 'single-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.MultiCheckbox,\n loadComponent: loadMultiCheckboxComponent,\n mapper: optionsFieldMapper,\n scope: 'multi-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Datepicker,\n loadComponent: loadDatepickerComponent,\n mapper: datepickerFieldMapper,\n scope: 'date',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Slider,\n loadComponent: loadSliderComponent,\n mapper: valueFieldMapper,\n scope: 'numeric',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Toggle,\n loadComponent: loadToggleComponent,\n mapper: checkboxFieldMapper,\n scope: 'boolean',\n ...VALUE_FIELD_TYPES_BASE,\n },\n];\n","/* eslint-disable @nx/enforce-module-boundaries -- Published secondary-entry imports must remain package specifiers for real lazy chunks. */\nimport type { Provider } from '@angular/core';\nimport { DynamicFormError, type AddonTypeDefinition } from '@ng-forge/dynamic-forms';\nimport { ADDON_TYPE_DEFINITIONS, type FieldTypeDefinition, type WrapperTypeDefinition } from '@ng-forge/dynamic-forms/integration';\nimport { IONIC_CONFIG, type IonicButtonAddon, type IonicConfig, type IonicIconAddon } from '@ng-forge/dynamic-forms-ionic/shared';\nimport { IONIC_FIELD_TYPES } from '../config/ionic-field-config';\n\n/** Field type definitions for Ionic components. */\nexport type IonicFieldTypes = FieldTypeDefinition[];\n\ntype IonicConfigFeature = {\n ɵkind: 'ionic-config';\n ɵproviders: Provider[];\n};\n\n/**\n * Default `withIonicFields()` shape — field defs + the auto-included\n * addons feature so `ion-icon` / `ion-button` work out of the box.\n */\ntype IonicFieldsWithAddons = [...IonicFieldTypes, IonicAddonsFeature, WrapperTypeDefinition];\n\ntype IonicFieldsWithConfig = [...IonicFieldTypes, IonicAddonsFeature, WrapperTypeDefinition, IonicConfigFeature];\n\n/**\n * Replaces the neutral core `field-errors` wrapper with the Ionic one, so\n * a container-level validation message renders like a field-level one.\n * Registered under the same name, so the later registration wins.\n */\nconst IONIC_FIELD_ERRORS_WRAPPER: WrapperTypeDefinition = {\n wrapperName: 'field-errors',\n loadComponent: () => import('../wrappers/field-errors/ionic-field-errors-wrapper.component'),\n rendersFieldErrors: true,\n};\n\n/**\n * Provides Ionic field type definitions for the dynamic form system,\n * with Ionic-shipped addon types (`ion-icon`, `ion-button`) auto-included\n * so addons work out of the box.\n *\n * @param config - Optional global configuration for Ionic form fields\n * @returns Tuple of field type definitions, the addons feature, and\n * optionally a config feature.\n */\nexport function withIonicFields(): IonicFieldsWithAddons;\nexport function withIonicFields(config: IonicConfig): IonicFieldsWithConfig;\nexport function withIonicFields(config: IonicConfig | undefined): IonicFieldsWithAddons | IonicFieldsWithConfig;\nexport function withIonicFields(config?: IonicConfig): IonicFieldsWithAddons | IonicFieldsWithConfig {\n // Always include the addons feature — ion-icon / ion-button are part of\n // the canonical Ionic surface.\n const base: unknown[] = [...IONIC_FIELD_TYPES, withIonicAddons(), IONIC_FIELD_ERRORS_WRAPPER];\n\n if (config) {\n base.push({\n ɵkind: 'ionic-config',\n ɵproviders: [{ provide: IONIC_CONFIG, useValue: config }],\n } satisfies IonicConfigFeature);\n return base as IonicFieldsWithConfig;\n }\n\n return base as IonicFieldsWithAddons;\n}\n\n/* -- Ionic addon types ------------------------------------------------- */\n\nconst ION_ICON_KIND: AddonTypeDefinition<IonicIconAddon> = {\n type: 'ion-icon',\n loadComponent: () => import('@ng-forge/dynamic-forms-ionic/lazy/addon-icon').then((m) => m.IonicIconAddonComponent),\n validate: (addon, fieldKey) => {\n if (typeof addon.icon !== 'string' || addon.icon.length === 0) {\n throw new DynamicFormError(`Addon type 'ion-icon' requires a non-empty 'icon' string (field: '${fieldKey}').`);\n }\n },\n};\n\nconst ION_BUTTON_KIND: AddonTypeDefinition<IonicButtonAddon> = {\n type: 'ion-button',\n loadComponent: () => import('@ng-forge/dynamic-forms-ionic/lazy/addon-button').then((m) => m.IonicButtonAddonComponent),\n validate: (addon, fieldKey) => {\n // Exactly one of preset / actionRef / action — validator drops the addon\n // (with warning) if the rule is violated.\n const set = [addon.preset, addon.actionRef, addon.action].filter((v) => v !== undefined);\n if (set.length > 1) {\n throw new DynamicFormError(\n `Addon type 'ion-button' on field '${fieldKey}' has more than one of preset/actionRef/action — exactly one allowed.`,\n );\n }\n // Icon-only buttons require ariaLabel for screen readers.\n if (addon.icon && !addon.label && !addon.ariaLabel) {\n throw new DynamicFormError(`Addon type 'ion-button' on field '${fieldKey}' is icon-only — provide 'ariaLabel' for accessibility.`);\n }\n },\n};\n\n/**\n * Feature type discriminant for the Ionic addons feature. Matches core's\n * `'addons'` type so providers flow through the standard addon-type pipeline\n * in `provideDynamicForm`.\n */\ntype IonicAddonsFeature = {\n ɵkind: 'addons';\n ɵproviders: Provider[];\n};\n\n/** Register Ionic-shipped addon types (`ion-icon`, `ion-button`) standalone. */\nexport function withIonicAddons(): IonicAddonsFeature {\n return {\n ɵkind: 'addons',\n ɵproviders: [\n { provide: ADDON_TYPE_DEFINITIONS, useValue: ION_ICON_KIND, multi: true },\n { provide: ADDON_TYPE_DEFINITIONS, useValue: ION_BUTTON_KIND, multi: true },\n ],\n };\n}\n","import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed } from '@angular/core';\nimport { IonButton, IonIcon, IonSpinner } from '@ionic/angular/standalone';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/integration';\nimport { injectNgForgeAddonAction, NgForgeAddonAction } from '@ng-forge/dynamic-forms/integration';\nimport type { IonicButtonAddon } from '@ng-forge/dynamic-forms-ionic/shared';\n\n/** Renderer for the `ion-button` addon type. */\n@Component({\n selector: 'df-ion-button-addon',\n imports: [IonButton, IonIcon, IonSpinner, DynamicTextPipe, AsyncPipe],\n hostDirectives: [NgForgeAddonAction],\n template: `\n <ion-button\n [attr.color]=\"color() ?? null\"\n [fill]=\"fill()\"\n [disabled]=\"action.disabled() || action.loading()\"\n [attr.aria-label]=\"(ariaLabel() | dynamicText | async) ?? null\"\n [attr.aria-busy]=\"action.loading() || null\"\n (click)=\"action.dispatch()\"\n >\n @if (action.loading()) {\n <ion-spinner [slot]=\"iconOnly() ? 'icon-only' : 'start'\" name=\"dots\"></ion-spinner>\n } @else if (icon(); as ic) {\n <ion-icon [name]=\"ic\" [slot]=\"iconOnly() ? 'icon-only' : 'start'\"></ion-icon>\n }\n @if (label(); as lbl) {\n {{ lbl | dynamicText | async }}\n }\n </ion-button>\n @if (action.loading()) {\n <span class=\"df-ion-sr-only\" role=\"status\">Loading…</span>\n }\n `,\n styles: [\n `\n .df-ion-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class IonicButtonAddonComponent {\n protected readonly action = injectNgForgeAddonAction<IonicButtonAddon>();\n\n /** Re-exposed for template binding — same signal stored on the directive. */\n protected readonly addon = this.action.addon;\n\n protected readonly label = computed(() => this.addon().label);\n protected readonly ariaLabel = computed(() => this.addon().ariaLabel);\n protected readonly icon = computed(() => this.addon().icon);\n /** Default color is undefined so the button inherits the theme's text color\n * (Ionic's `medium` would force low-contrast grey, which fails WCAG on dark\n * surfaces). Consumers can still set `color: 'primary' | 'success' | ...`\n * explicitly when they want adapter-styled coloring. */\n protected readonly color = computed(() => this.addon().color);\n protected readonly fill = computed(() => this.addon().fill ?? 'clear');\n /** Icon-only when there is an icon but no label — drives the `slot` choice.\n * Truthy check on `label` mirrors Material's heuristic; empty-string label\n * is treated as \"no label\" so the button doesn't render an invisible text\n * slot beside the icon. */\n protected readonly iconOnly = computed(() => !!this.icon() && !this.label());\n}\n","import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { IonIcon } from '@ionic/angular/standalone';\nimport { WrapperFieldInputs } from '@ng-forge/dynamic-forms/integration';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/integration';\nimport type { IonicIconAddon } from '@ng-forge/dynamic-forms-ionic/shared';\n\n/** Renderer for the `ion-icon` addon type. */\n@Component({\n selector: 'df-ion-icon-addon',\n imports: [IonIcon, AsyncPipe, DynamicTextPipe],\n template: `<ion-icon [name]=\"iconName()\" [attr.aria-label]=\"(ariaLabel() | dynamicText | async) ?? null\"></ion-icon>`,\n host: {\n '[attr.aria-hidden]': 'hasAriaLabel() ? null : \"true\"',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class IonicIconAddonComponent {\n readonly addon = input.required<IonicIconAddon>();\n /** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every type must declare it. */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n\n protected readonly iconName = computed(() => this.addon().icon);\n protected readonly ariaLabel = computed(() => this.addon().ariaLabel);\n protected readonly hasAriaLabel = computed(() => this.addon().ariaLabel !== undefined);\n}\n"]}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-ionic.mjs","mappings":";;;;;;AAIO;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACXI;AACJ;AACA;AACA;;;AAKE;AACE;AACA;;;AAKA;;;AAKA;;QAIF;AACA;;AAGI;;AACA;AACF;;;;AAKE;AACA;AACE;;;;;AAMN;AACF;AACF;;;ACvCA;;;AAIA;AACE;AACA;;AAGF;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAIA;AAEA;AAEA;AAOO;AACL;;AAEE;AACA;;AAEA;AACA;AACE;AACD;AACD;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;;AAEA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;;;;AC1JH;AACE;AACA;AACA;;AAeI;;;;AAOA;;AAE4B;AAC9B;;AAGF;AACF;AAEA;AAEA;AACE;AACA;AACA;AACE;AACE;;;;AAKN;AACE;AACA;AACA;;AAIE;AACE;;QAKF;AACE;;;;;;AAkBF;AACA;;;AAGC;;AAEL;;;AChHA","names":[],"ignoreList":[],"sources":["../../../../packages/dynamic-forms-ionic/src/lib/types/types.ts","../../../../packages/dynamic-forms-ionic/src/lib/fields/button/ionic-button.mapper.ts","../../../../packages/dynamic-forms-ionic/src/lib/config/ionic-field-config.ts","../../../../packages/dynamic-forms-ionic/src/lib/providers/ionic-providers.ts","../../../../packages/dynamic-forms-ionic/src/index.ts"],"sourcesContent":["/**\n * Ionic field type constants\n * Based on available field components in the /fields folder\n */\nexport const IonicField = {\n Input: 'input',\n Select: 'select',\n Checkbox: 'checkbox',\n Button: 'button',\n Submit: 'submit',\n Next: 'next',\n Previous: 'previous',\n AddArrayItem: 'add-array-item',\n PrependArrayItem: 'prepend-array-item',\n InsertArrayItem: 'insert-array-item',\n RemoveArrayItem: 'remove-array-item',\n PopArrayItem: 'pop-array-item',\n ShiftArrayItem: 'shift-array-item',\n Textarea: 'textarea',\n Radio: 'radio',\n MultiCheckbox: 'multi-checkbox',\n Datepicker: 'datepicker',\n Slider: 'slider',\n Toggle: 'toggle',\n} as const;\n\nexport type IonicFieldType = (typeof IonicField)[keyof typeof IonicField];\n","import { computed, inject, isSignal, Signal } from '@angular/core';\nimport { FieldDef } from '@ng-forge/dynamic-forms';\nimport { ARRAY_CONTEXT, buildBaseInputs, DEFAULT_PROPS, injectNonFieldLogicResolver } from '@ng-forge/dynamic-forms/integration';\n\n/**\n * Generic button mapper for custom events or basic buttons.\n * For specific button types (submit, next, prev, add/remove array items),\n * use the dedicated field types and their specific mappers.\n *\n * @param fieldDef The button field definition\n * @returns Signal containing Record of input names to values for ngComponentOutlet\n */\nexport function buttonFieldMapper(fieldDef: FieldDef<Record<string, unknown>>): Signal<Record<string, unknown>> {\n const defaultProps = inject(DEFAULT_PROPS);\n const arrayContext = inject(ARRAY_CONTEXT, { optional: true });\n const resolveLogic = injectNonFieldLogicResolver(fieldDef);\n\n return computed(() => {\n const baseInputs = buildBaseInputs(fieldDef, defaultProps());\n\n const inputs: Record<string, unknown> = {\n ...baseInputs,\n ...resolveLogic(),\n };\n\n // Add event binding for button events\n if ('event' in fieldDef && fieldDef.event !== undefined) {\n inputs['event'] = fieldDef.event;\n }\n\n // Add eventArgs binding if provided\n if ('eventArgs' in fieldDef && fieldDef.eventArgs !== undefined) {\n inputs['eventArgs'] = fieldDef.eventArgs;\n }\n\n // Add eventContext for token resolution (supports $template, $arrayKey, $index, etc.)\n const template = 'template' in fieldDef ? fieldDef.template : undefined;\n if (template || arrayContext) {\n // Read signal value if index is a signal (supports differential updates)\n const getIndex = () => {\n if (!arrayContext) return -1;\n return isSignal(arrayContext.index) ? arrayContext.index() : arrayContext.index;\n };\n\n inputs['eventContext'] = {\n key: fieldDef.key,\n index: getIndex(),\n arrayKey: arrayContext?.arrayKey ?? '',\n get formValue() {\n return arrayContext?.formValue ?? {};\n },\n template,\n };\n }\n\n return inputs;\n });\n}\n","/* eslint-disable @nx/enforce-module-boundaries -- Published secondary-entry imports must remain package specifiers for real lazy chunks. */\nimport { FieldTypeDefinition } from '@ng-forge/dynamic-forms/integration';\nimport {\n addArrayItemButtonMapper,\n checkboxFieldMapper,\n datepickerFieldMapper,\n insertArrayItemButtonMapper,\n optionsFieldMapper,\n popArrayItemButtonMapper,\n prependArrayItemButtonMapper,\n removeArrayItemButtonMapper,\n shiftArrayItemButtonMapper,\n valueFieldMapper,\n} from '@ng-forge/dynamic-forms/integration';\nimport { IonicField } from '../types/types';\nimport { buttonFieldMapper } from '../fields/button/ionic-button.mapper';\nimport { nextButtonFieldMapper, previousButtonFieldMapper, submitButtonFieldMapper } from '../fields/button/ionic-specific-button.mapper';\n\nconst VALUE_FIELD_TYPES_BASE = {\n renderReadyWhen: ['field'],\n} as const;\n\nconst BUTTON_FIELD_TYPES_BASE = {\n renderReadyWhen: [],\n valueHandling: 'exclude',\n} as const;\n\nconst loadInputComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/input').then(({ IonicInputFieldComponent }) => IonicInputFieldComponent);\nconst loadSelectComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/select').then(({ IonicSelectFieldComponent }) => IonicSelectFieldComponent);\nconst loadCheckboxComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/checkbox').then(({ IonicCheckboxFieldComponent }) => IonicCheckboxFieldComponent);\nconst loadButtonComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/button').then(({ IonicButtonFieldComponent }) => IonicButtonFieldComponent);\nconst loadTextareaComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/textarea').then(({ IonicTextareaFieldComponent }) => IonicTextareaFieldComponent);\nconst loadRadioComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/radio').then(({ IonicRadioFieldComponent }) => IonicRadioFieldComponent);\nconst loadMultiCheckboxComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/multi-checkbox').then(\n ({ IonicMultiCheckboxFieldComponent }) => IonicMultiCheckboxFieldComponent,\n );\nconst loadDatepickerComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/datepicker').then(({ IonicDatepickerFieldComponent }) => IonicDatepickerFieldComponent);\nconst loadSliderComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/slider').then(({ IonicSliderFieldComponent }) => IonicSliderFieldComponent);\nconst loadToggleComponent = () =>\n import('@ng-forge/dynamic-forms-ionic/lazy/toggle').then(({ IonicToggleFieldComponent }) => IonicToggleFieldComponent);\n\n/**\n * Ionic field type definitions\n * Follows the FieldTypeDefinition interface for proper registry integration\n */\nexport const IONIC_FIELD_TYPES: FieldTypeDefinition[] = [\n {\n name: IonicField.Input,\n loadComponent: loadInputComponent,\n mapper: valueFieldMapper,\n propsToMeta: ['type'],\n scope: ['text-input', 'numeric'],\n addons: {\n slots: ['prefix', 'suffix'],\n },\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Select,\n loadComponent: loadSelectComponent,\n mapper: optionsFieldMapper,\n scope: 'single-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Checkbox,\n loadComponent: loadCheckboxComponent,\n mapper: checkboxFieldMapper,\n scope: 'boolean',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Button,\n loadComponent: loadButtonComponent,\n mapper: buttonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Submit,\n loadComponent: loadButtonComponent,\n mapper: submitButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Next,\n loadComponent: loadButtonComponent,\n mapper: nextButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Previous,\n loadComponent: loadButtonComponent,\n mapper: previousButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.AddArrayItem,\n loadComponent: loadButtonComponent,\n mapper: addArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.PrependArrayItem,\n loadComponent: loadButtonComponent,\n mapper: prependArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.InsertArrayItem,\n loadComponent: loadButtonComponent,\n mapper: insertArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.RemoveArrayItem,\n loadComponent: loadButtonComponent,\n mapper: removeArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.PopArrayItem,\n loadComponent: loadButtonComponent,\n mapper: popArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.ShiftArrayItem,\n loadComponent: loadButtonComponent,\n mapper: shiftArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Textarea,\n loadComponent: loadTextareaComponent,\n mapper: valueFieldMapper,\n propsToMeta: ['rows'],\n scope: 'text-input',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Radio,\n loadComponent: loadRadioComponent,\n mapper: optionsFieldMapper,\n scope: 'single-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.MultiCheckbox,\n loadComponent: loadMultiCheckboxComponent,\n mapper: optionsFieldMapper,\n scope: 'multi-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Datepicker,\n loadComponent: loadDatepickerComponent,\n mapper: datepickerFieldMapper,\n scope: 'date',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Slider,\n loadComponent: loadSliderComponent,\n mapper: valueFieldMapper,\n scope: 'numeric',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: IonicField.Toggle,\n loadComponent: loadToggleComponent,\n mapper: checkboxFieldMapper,\n scope: 'boolean',\n ...VALUE_FIELD_TYPES_BASE,\n },\n];\n","/* eslint-disable @nx/enforce-module-boundaries -- Published secondary-entry imports must remain package specifiers for real lazy chunks. */\nimport type { Provider } from '@angular/core';\nimport { DynamicFormError, type AddonTypeDefinition } from '@ng-forge/dynamic-forms';\nimport { ADDON_TYPE_DEFINITIONS, type FieldTypeDefinition, type WrapperTypeDefinition } from '@ng-forge/dynamic-forms/integration';\nimport { IONIC_CONFIG, type IonicButtonAddon, type IonicConfig, type IonicIconAddon } from '@ng-forge/dynamic-forms-ionic/shared';\nimport { IONIC_FIELD_TYPES } from '../config/ionic-field-config';\n\n/** Field type definitions for Ionic components. */\nexport type IonicFieldTypes = FieldTypeDefinition[];\n\ntype IonicConfigFeature = {\n ɵkind: 'ionic-config';\n ɵproviders: Provider[];\n};\n\n/**\n * Default `withIonicFields()` shape — field defs + the auto-included\n * addons feature so `ion-icon` / `ion-button` work out of the box.\n */\ntype IonicFieldsWithAddons = [...IonicFieldTypes, IonicAddonsFeature, WrapperTypeDefinition];\n\ntype IonicFieldsWithConfig = [...IonicFieldTypes, IonicAddonsFeature, WrapperTypeDefinition, IonicConfigFeature];\n\n/**\n * Replaces the neutral core `field-errors` wrapper with the Ionic one, so\n * a container-level validation message renders like a field-level one.\n * Registered under the same name, so the later registration wins.\n */\nconst IONIC_FIELD_ERRORS_WRAPPER: WrapperTypeDefinition = {\n wrapperName: 'field-errors',\n loadComponent: () => import('../wrappers/field-errors/ionic-field-errors-wrapper.component'),\n rendersFieldErrors: true,\n};\n\n/**\n * Provides Ionic field type definitions for the dynamic form system,\n * with Ionic-shipped addon types (`ion-icon`, `ion-button`) auto-included\n * so addons work out of the box.\n *\n * @param config - Optional global configuration for Ionic form fields\n * @returns Tuple of field type definitions, the addons feature, and\n * optionally a config feature.\n */\nexport function withIonicFields(): IonicFieldsWithAddons;\nexport function withIonicFields(config: IonicConfig): IonicFieldsWithConfig;\nexport function withIonicFields(config: IonicConfig | undefined): IonicFieldsWithAddons | IonicFieldsWithConfig;\nexport function withIonicFields(config?: IonicConfig): IonicFieldsWithAddons | IonicFieldsWithConfig {\n // Always include the addons feature — ion-icon / ion-button are part of\n // the canonical Ionic surface.\n const base: unknown[] = [...IONIC_FIELD_TYPES, withIonicAddons(), IONIC_FIELD_ERRORS_WRAPPER];\n\n if (config) {\n base.push({\n ɵkind: 'ionic-config',\n ɵproviders: [{ provide: IONIC_CONFIG, useValue: config }],\n } satisfies IonicConfigFeature);\n return base as IonicFieldsWithConfig;\n }\n\n return base as IonicFieldsWithAddons;\n}\n\n/* -- Ionic addon types ------------------------------------------------- */\n\nconst ION_ICON_KIND: AddonTypeDefinition<IonicIconAddon> = {\n type: 'ion-icon',\n loadComponent: () => import('@ng-forge/dynamic-forms-ionic/lazy/addon-icon').then((m) => m.IonicIconAddonComponent),\n validate: (addon, fieldKey) => {\n if (typeof addon.icon !== 'string' || addon.icon.length === 0) {\n throw new DynamicFormError(`Addon type 'ion-icon' requires a non-empty 'icon' string (field: '${fieldKey}').`);\n }\n },\n};\n\nconst ION_BUTTON_KIND: AddonTypeDefinition<IonicButtonAddon> = {\n type: 'ion-button',\n loadComponent: () => import('@ng-forge/dynamic-forms-ionic/lazy/addon-button').then((m) => m.IonicButtonAddonComponent),\n validate: (addon, fieldKey) => {\n // Exactly one of preset / actionRef / action — validator drops the addon\n // (with warning) if the rule is violated.\n const set = [addon.preset, addon.actionRef, addon.action].filter((v) => v !== undefined);\n if (set.length > 1) {\n throw new DynamicFormError(\n `Addon type 'ion-button' on field '${fieldKey}' has more than one of preset/actionRef/action — exactly one allowed.`,\n );\n }\n // Icon-only buttons require ariaLabel for screen readers.\n if (addon.icon && !addon.label && !addon.ariaLabel) {\n throw new DynamicFormError(`Addon type 'ion-button' on field '${fieldKey}' is icon-only — provide 'ariaLabel' for accessibility.`);\n }\n },\n};\n\n/**\n * Feature type discriminant for the Ionic addons feature. Matches core's\n * `'addons'` type so providers flow through the standard addon-type pipeline\n * in `provideDynamicForm`.\n */\ntype IonicAddonsFeature = {\n ɵkind: 'addons';\n ɵproviders: Provider[];\n};\n\n/** Register Ionic-shipped addon types (`ion-icon`, `ion-button`) standalone. */\nexport function withIonicAddons(): IonicAddonsFeature {\n return {\n ɵkind: 'addons',\n ɵproviders: [\n { provide: ADDON_TYPE_DEFINITIONS, useValue: ION_ICON_KIND, multi: true },\n { provide: ADDON_TYPE_DEFINITIONS, useValue: ION_BUTTON_KIND, multi: true },\n ],\n };\n}\n","/* eslint-disable @nx/enforce-module-boundaries -- Package self-imports preserve ng-packagr secondary entry points. */\nexport { IONIC_FIELD_TYPES, IONIC_CONFIG, IonicField, withIonicFields, withIonicAddons, IONIC_INPUT_TYPE_OVERRIDE } from './lib';\nexport type {\n IonicButtonProps,\n IonicButtonField,\n IonicSubmitButtonField,\n IonicNextButtonField,\n IonicPreviousButtonField,\n IonicAddArrayItemButtonField,\n IonicPrependArrayItemButtonField,\n IonicInsertArrayItemButtonField,\n IonicRemoveArrayItemButtonField,\n IonicPopArrayItemButtonField,\n IonicShiftArrayItemButtonField,\n IonicCheckboxProps,\n IonicCheckboxField,\n IonicDatepickerProps,\n IonicDatepickerField,\n IonicInputProps,\n IonicInputField,\n IonicMultiCheckboxProps,\n IonicMultiCheckboxField,\n IonicRadioProps,\n IonicRadioField,\n IonicSelectProps,\n IonicSelectField,\n IonicSliderProps,\n IonicSliderField,\n IonicTextareaProps,\n IonicTextareaField,\n IonicToggleProps,\n IonicToggleField,\n IonicConfig,\n IonicFieldType,\n IonicFormProps,\n IonicFormConfig,\n IonicAddon,\n IonicButtonAddon,\n IonicIconAddon,\n IonicInputAddon,\n IonicAddonExtensions,\n} from './lib';\n\n// Component classes load from the lazy entries. Re-exporting their values here would bundle them\n// eagerly, and compiling them into this entry creates duplicate classes (NG0912, #625).\nimport type { FormEvent } from '@ng-forge/dynamic-forms';\nimport type { IonicButtonFieldComponent as IonicButtonFieldComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/button';\nimport type { IonicCheckboxFieldComponent as IonicCheckboxFieldComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/checkbox';\nimport type { IonicDatepickerFieldComponent as IonicDatepickerFieldComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/datepicker';\nimport type { IonicInputFieldComponent as IonicInputFieldComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/input';\nimport type { IonicMultiCheckboxFieldComponent as IonicMultiCheckboxFieldComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/multi-checkbox';\nimport type { IonicRadioFieldComponent as IonicRadioFieldComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/radio';\nimport type { IonicSelectFieldComponent as IonicSelectFieldComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/select';\nimport type { IonicSliderFieldComponent as IonicSliderFieldComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/slider';\nimport type { IonicTextareaFieldComponent as IonicTextareaFieldComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/textarea';\nimport type { IonicToggleFieldComponent as IonicToggleFieldComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/toggle';\nimport type { IonicIconAddonComponent as IonicIconAddonComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/addon-icon';\nimport type { IonicButtonAddonComponent as IonicButtonAddonComponentClass } from '@ng-forge/dynamic-forms-ionic/lazy/addon-button';\n\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/button`. Import it from there to use the class as a value. */\nexport type IonicButtonFieldComponent<TEvent extends FormEvent> = IonicButtonFieldComponentClass<TEvent>;\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/checkbox`. Import it from there to use the class as a value. */\nexport type IonicCheckboxFieldComponent = IonicCheckboxFieldComponentClass;\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/datepicker`. Import it from there to use the class as a value. */\nexport type IonicDatepickerFieldComponent = IonicDatepickerFieldComponentClass;\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/input`. Import it from there to use the class as a value. */\nexport type IonicInputFieldComponent = IonicInputFieldComponentClass;\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/multi-checkbox`. Import it from there to use the class as a value. */\nexport type IonicMultiCheckboxFieldComponent = IonicMultiCheckboxFieldComponentClass;\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/radio`. Import it from there to use the class as a value. */\nexport type IonicRadioFieldComponent = IonicRadioFieldComponentClass;\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/select`. Import it from there to use the class as a value. */\nexport type IonicSelectFieldComponent = IonicSelectFieldComponentClass;\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/slider`. Import it from there to use the class as a value. */\nexport type IonicSliderFieldComponent = IonicSliderFieldComponentClass;\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/textarea`. Import it from there to use the class as a value. */\nexport type IonicTextareaFieldComponent = IonicTextareaFieldComponentClass;\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/toggle`. Import it from there to use the class as a value. */\nexport type IonicToggleFieldComponent = IonicToggleFieldComponentClass;\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/addon-icon`. Import it from there to use the class as a value. */\nexport type IonicIconAddonComponent = IonicIconAddonComponentClass;\n/** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/addon-button`. Import it from there to use the class as a value. */\nexport type IonicButtonAddonComponent = IonicButtonAddonComponentClass;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-forge/dynamic-forms-ionic",
3
- "version": "1.2.0-next.9",
3
+ "version": "1.3.0-next.1",
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",
@@ -95,7 +95,7 @@
95
95
  "@angular/core": "^22.0.0",
96
96
  "@angular/forms": "^22.0.0",
97
97
  "@ionic/angular": ">=8.0.0",
98
- "@ng-forge/dynamic-forms": "~1.2.0-next.9",
98
+ "@ng-forge/dynamic-forms": "~1.3.0-next.1",
99
99
  "rxjs": ">=7.0.0"
100
100
  },
101
101
  "dependencies": {
@@ -105,4 +105,4 @@
105
105
  },
106
106
  "module": "fesm2022/ng-forge-dynamic-forms-ionic.mjs",
107
107
  "typings": "types/ng-forge-dynamic-forms-ionic.d.ts"
108
- }
108
+ }
@@ -1,12 +1,20 @@
1
- import * as _ng_forge_dynamic_forms from '@ng-forge/dynamic-forms';
2
- import { FormEvent, FormSubmitEvent, NextPageEvent, PreviousPageEvent, AppendArrayItemEvent, ArrayAllowedChildren, PrependArrayItemEvent, InsertArrayItemEvent, RemoveAtIndexEvent, PopArrayItemEvent, ShiftArrayItemEvent, DynamicText, TextAddon, TemplateAddon, ValueType, FieldOption, NarrowFields, RegisteredFieldTypes, InferFormValue, FormConfig } from '@ng-forge/dynamic-forms';
3
- import * as i1 from '@ng-forge/dynamic-forms/integration';
4
- import { ButtonField, CheckboxField, DatepickerField, DatepickerProps, InputField, InputProps, WrapperFieldInputs, MultiCheckboxField, RadioField, SelectField, SelectProps, SliderField, TextareaField, TextareaProps, ToggleField, FieldTypeDefinition, WrapperTypeDefinition } from '@ng-forge/dynamic-forms/integration';
5
- import * as _angular_core from '@angular/core';
6
- import { Provider } from '@angular/core';
1
+ import { FormEvent, FormSubmitEvent, NextPageEvent, PreviousPageEvent, AppendArrayItemEvent, ArrayAllowedChildren, PrependArrayItemEvent, InsertArrayItemEvent, RemoveAtIndexEvent, PopArrayItemEvent, ShiftArrayItemEvent, DynamicText, TextAddon, TemplateAddon, ValueType, NarrowFields, RegisteredFieldTypes, InferFormValue, FormConfig } from '@ng-forge/dynamic-forms';
2
+ import { ButtonField, CheckboxField, DatepickerField, DatepickerProps, InputField, InputProps, MultiCheckboxField, RadioField, SelectField, SelectProps, SliderField, TextareaField, TextareaProps, ToggleField, FieldTypeDefinition, WrapperTypeDefinition } from '@ng-forge/dynamic-forms/integration';
7
3
  import { IonicIconAddon, IonicButtonAddon, IonicConfig } from '@ng-forge/dynamic-forms-ionic/shared';
8
4
  export { IONIC_CONFIG, IONIC_INPUT_TYPE_OVERRIDE, IonicAddon, IonicButtonAddon, IonicConfig, IonicIconAddon } from '@ng-forge/dynamic-forms-ionic/shared';
9
- import * as _ng_forge_dynamic_forms_ionic from '@ng-forge/dynamic-forms-ionic';
5
+ import { IonicButtonFieldComponent as IonicButtonFieldComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/button';
6
+ import { IonicCheckboxFieldComponent as IonicCheckboxFieldComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/checkbox';
7
+ import { IonicDatepickerFieldComponent as IonicDatepickerFieldComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/datepicker';
8
+ import { IonicInputFieldComponent as IonicInputFieldComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/input';
9
+ import { IonicMultiCheckboxFieldComponent as IonicMultiCheckboxFieldComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/multi-checkbox';
10
+ import { IonicRadioFieldComponent as IonicRadioFieldComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/radio';
11
+ import { IonicSelectFieldComponent as IonicSelectFieldComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/select';
12
+ import { IonicSliderFieldComponent as IonicSliderFieldComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/slider';
13
+ import { IonicTextareaFieldComponent as IonicTextareaFieldComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/textarea';
14
+ import { IonicToggleFieldComponent as IonicToggleFieldComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/toggle';
15
+ import { IonicIconAddonComponent as IonicIconAddonComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/addon-icon';
16
+ import { IonicButtonAddonComponent as IonicButtonAddonComponent$1 } from '@ng-forge/dynamic-forms-ionic/lazy/addon-button';
17
+ import { Provider } from '@angular/core';
10
18
 
11
19
  interface IonicButtonProps {
12
20
  expand?: 'full' | 'block';
@@ -110,16 +118,6 @@ type IonicShiftArrayItemButtonField = Omit<IonicButtonField<ShiftArrayItemEvent>
110
118
  arrayKey: string;
111
119
  };
112
120
 
113
- declare class IonicButtonFieldComponent<TEvent extends FormEvent> {
114
- protected readonly action: i1.NgForgeAction<TEvent>;
115
- readonly props: _angular_core.InputSignal<IonicButtonProps | undefined>;
116
- readonly buttonType: _angular_core.Signal<"button" | "submit" | "reset">;
117
- readonly buttonTestId: _angular_core.Signal<string>;
118
- onClick(): void;
119
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicButtonFieldComponent<any>, never>;
120
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicButtonFieldComponent<any>, "df-ion-button", never, { "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NgForgeActionHost; inputs: {}; outputs: {}; }]>;
121
- }
122
-
123
121
  interface IonicCheckboxProps {
124
122
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
125
123
  justify?: 'start' | 'end' | 'space-between';
@@ -129,13 +127,6 @@ interface IonicCheckboxProps {
129
127
  }
130
128
  type IonicCheckboxField = CheckboxField<IonicCheckboxProps>;
131
129
 
132
- declare class IonicCheckboxFieldComponent {
133
- protected readonly ngf: i1.TypedNgForgeField<boolean>;
134
- readonly props: _angular_core.InputSignal<IonicCheckboxProps | undefined>;
135
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicCheckboxFieldComponent, never>;
136
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicCheckboxFieldComponent, "df-ion-checkbox", never, { "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NgForgeFieldHost; inputs: {}; outputs: {}; }]>;
137
- }
138
-
139
130
  interface IonicDatepickerProps extends DatepickerProps {
140
131
  presentation?: 'date' | 'date-time' | 'time' | 'time-date' | 'month' | 'month-year' | 'year';
141
132
  multiple?: boolean;
@@ -152,22 +143,6 @@ interface IonicDatepickerProps extends DatepickerProps {
152
143
  }
153
144
  type IonicDatepickerField = DatepickerField<IonicDatepickerProps>;
154
145
 
155
- declare class IonicDatepickerFieldComponent {
156
- protected readonly ngf: i1.TypedNgForgeField<Date | null>;
157
- readonly minDate: _angular_core.InputSignal<Date | null>;
158
- readonly maxDate: _angular_core.InputSignal<Date | null>;
159
- readonly startAt: _angular_core.InputSignal<Date | null>;
160
- readonly props: _angular_core.InputSignal<IonicDatepickerProps | undefined>;
161
- readonly isModalOpen: _angular_core.WritableSignal<boolean>;
162
- openModal(): void;
163
- closeModal(): void;
164
- onDateChange(event: CustomEvent): void;
165
- dateToIsoString(date: Date | null | undefined): string | undefined;
166
- formatDisplayDate(date: Date | null | undefined): string;
167
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicDatepickerFieldComponent, never>;
168
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicDatepickerFieldComponent, "df-ion-datepicker", never, { "minDate": { "alias": "minDate"; "required": false; "isSignal": true; }; "maxDate": { "alias": "maxDate"; "required": false; "isSignal": true; }; "startAt": { "alias": "startAt"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NgForgeFieldHost; inputs: {}; outputs: {}; }]>;
169
- }
170
-
171
146
  interface IonicInputProps extends InputProps {
172
147
  fill?: 'solid' | 'outline';
173
148
  shape?: 'round';
@@ -191,43 +166,6 @@ type IonicInputField = InputField<IonicInputProps> & {
191
166
  addons?: ReadonlyArray<IonicInputAddon>;
192
167
  };
193
168
 
194
- declare class IonicInputFieldComponent {
195
- private readonly elementRef;
196
- private ionicConfig;
197
- protected readonly ngf: i1.TypedNgForgeField<string>;
198
- protected readonly ngfa: i1.TypedNgForgeAddons<IonicInputAddon>;
199
- readonly props: _angular_core.InputSignal<IonicInputProps | undefined>;
200
- /**
201
- * Wrapper-style host bag pushed by `DfFieldOutlet`. Declared at the
202
- * component level so `setInputIfDeclared` (which uses
203
- * `reflectComponentType`) can write it.
204
- */
205
- readonly fieldInputs: _angular_core.InputSignal<WrapperFieldInputs | undefined>;
206
- /** Per-instance type override populated by `toggle-password-visibility` preset. */
207
- private readonly typeOverride;
208
- protected readonly fill: _angular_core.Signal<"outline" | "solid">;
209
- protected readonly shape: _angular_core.Signal<"round" | undefined>;
210
- /** Bootstrap / PrimeNG. Consumers can opt into Ionic's native inline 'start' */
211
- protected readonly labelPlacement: _angular_core.Signal<"start" | "end" | "fixed" | "stacked" | "floating">;
212
- protected readonly color: _angular_core.Signal<"primary" | "secondary" | "tertiary" | "success" | "warning" | "danger" | "light" | "medium" | "dark" | undefined>;
213
- /** Override (set by `toggle-password-visibility` preset) wins over `props().type`. */
214
- protected readonly type: _angular_core.Signal<string>;
215
- /** Per-type split: ion-button addons render inline via the attribute-
216
- * selector inline component (so the slotted element is a native
217
- * <ion-button> Ionic can style); everything else (icon/text/template/
218
- * component types) goes through the universal <df-addon-slot> dispatcher
219
- * wrapped in <span slot="start|end"> for safe shadow-DOM projection. */
220
- protected readonly buttonPrefixAddons: _angular_core.Signal<_ng_forge_dynamic_forms_ionic.IonicButtonAddon[]>;
221
- protected readonly buttonSuffixAddons: _angular_core.Signal<_ng_forge_dynamic_forms_ionic.IonicButtonAddon[]>;
222
- protected readonly decorativePrefixAddons: _angular_core.Signal<(_ng_forge_dynamic_forms.TextAddon | _ng_forge_dynamic_forms.TemplateAddon | _ng_forge_dynamic_forms_ionic.IonicIconAddon)[]>;
223
- protected readonly decorativeSuffixAddons: _angular_core.Signal<(_ng_forge_dynamic_forms.TextAddon | _ng_forge_dynamic_forms.TemplateAddon | _ng_forge_dynamic_forms_ionic.IonicIconAddon)[]>;
224
- /** Set when the component is destroyed — guards async aria-describedby sync against teardown. */
225
- private destroyed;
226
- constructor();
227
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicInputFieldComponent, never>;
228
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicInputFieldComponent, "df-ion-input", never, { "props": { "alias": "props"; "required": false; "isSignal": true; }; "fieldInputs": { "alias": "fieldInputs"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NgForgeFieldHost; inputs: {}; outputs: {}; }, { directive: typeof i1.NgForgeAddons; inputs: {}; outputs: {}; }]>;
229
- }
230
-
231
169
  interface IonicMultiCheckboxProps {
232
170
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
233
171
  justify?: 'start' | 'end' | 'space-between';
@@ -236,19 +174,6 @@ interface IonicMultiCheckboxProps {
236
174
  }
237
175
  type IonicMultiCheckboxField<T> = MultiCheckboxField<T, IonicMultiCheckboxProps>;
238
176
 
239
- declare class IonicMultiCheckboxFieldComponent {
240
- protected readonly ngf: i1.TypedNgForgeField<ValueType[]>;
241
- readonly options: _angular_core.InputSignal<FieldOption<ValueType>[]>;
242
- readonly props: _angular_core.InputSignal<IonicMultiCheckboxProps | undefined>;
243
- valueViewModel: _angular_core.WritableSignal<FieldOption<ValueType>[]>;
244
- /** Computed map of checked option values for O(1) lookup in template */
245
- readonly checkedValuesMap: _angular_core.Signal<Record<string, boolean>>;
246
- constructor();
247
- onCheckboxChange(option: FieldOption<ValueType>, checked: boolean): void;
248
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicMultiCheckboxFieldComponent, never>;
249
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicMultiCheckboxFieldComponent, "df-ion-multi-checkbox", never, { "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NgForgeFieldHost; inputs: {}; outputs: {}; }]>;
250
- }
251
-
252
177
  interface IonicRadioProps {
253
178
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
254
179
  justify?: 'start' | 'end' | 'space-between';
@@ -258,15 +183,6 @@ interface IonicRadioProps {
258
183
  }
259
184
  type IonicRadioField<T> = RadioField<T, IonicRadioProps>;
260
185
 
261
- declare class IonicRadioFieldComponent {
262
- protected readonly ngf: i1.TypedNgForgeField<ValueType>;
263
- readonly options: _angular_core.InputSignal<FieldOption<ValueType>[]>;
264
- readonly props: _angular_core.InputSignal<IonicRadioProps | undefined>;
265
- defaultCompare: (value1: any, value2: any) => boolean;
266
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicRadioFieldComponent, never>;
267
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicRadioFieldComponent, "df-ion-radio", never, { "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NgForgeFieldHost; inputs: {}; outputs: {}; }]>;
268
- }
269
-
270
186
  interface IonicSelectProps extends SelectProps {
271
187
  multiple?: boolean;
272
188
  interface?: 'action-sheet' | 'popover' | 'alert';
@@ -282,15 +198,6 @@ interface IonicSelectProps extends SelectProps {
282
198
  }
283
199
  type IonicSelectField<T> = SelectField<T, IonicSelectProps>;
284
200
 
285
- declare class IonicSelectFieldComponent {
286
- protected readonly ngf: i1.TypedNgForgeField<ValueType>;
287
- readonly options: _angular_core.InputSignal<FieldOption<ValueType>[]>;
288
- readonly props: _angular_core.InputSignal<IonicSelectProps | undefined>;
289
- defaultCompare: (value1: any, value2: any) => boolean;
290
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicSelectFieldComponent, never>;
291
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicSelectFieldComponent, "df-ion-select", never, { "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NgForgeFieldHost; inputs: {}; outputs: {}; }]>;
292
- }
293
-
294
201
  interface IonicSliderProps {
295
202
  /**
296
203
  * Adapter-level override for the slider minimum.
@@ -318,15 +225,6 @@ interface IonicSliderProps {
318
225
  }
319
226
  type IonicSliderField = SliderField<IonicSliderProps>;
320
227
 
321
- declare class IonicSliderFieldComponent {
322
- protected readonly ngf: i1.TypedNgForgeField<number>;
323
- readonly step: _angular_core.InputSignal<number | undefined>;
324
- readonly props: _angular_core.InputSignal<IonicSliderProps | undefined>;
325
- protected defaultPinFormatter: (value: number) => string;
326
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicSliderFieldComponent, never>;
327
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicSliderFieldComponent, "df-ion-slider", never, { "step": { "alias": "step"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NgForgeFieldHost; inputs: {}; outputs: {}; }, { directive: typeof i1.NgForgeHostControl; inputs: {}; outputs: {}; }]>;
328
- }
329
-
330
228
  interface IonicTextareaProps extends TextareaProps {
331
229
  autoGrow?: boolean;
332
230
  counter?: boolean;
@@ -339,15 +237,6 @@ interface IonicTextareaProps extends TextareaProps {
339
237
  }
340
238
  type IonicTextareaField = TextareaField<IonicTextareaProps>;
341
239
 
342
- declare class IonicTextareaFieldComponent {
343
- private readonly elementRef;
344
- protected readonly ngf: i1.TypedNgForgeField<string>;
345
- readonly props: _angular_core.InputSignal<IonicTextareaProps | undefined>;
346
- constructor();
347
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicTextareaFieldComponent, never>;
348
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicTextareaFieldComponent, "df-ion-textarea", never, { "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NgForgeFieldHost; inputs: {}; outputs: {}; }]>;
349
- }
350
-
351
240
  interface IonicToggleProps {
352
241
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
353
242
  justify?: 'start' | 'end' | 'space-between';
@@ -357,13 +246,6 @@ interface IonicToggleProps {
357
246
  }
358
247
  type IonicToggleField = ToggleField<IonicToggleProps>;
359
248
 
360
- declare class IonicToggleFieldComponent {
361
- protected readonly ngf: i1.TypedNgForgeField<boolean>;
362
- readonly props: _angular_core.InputSignal<IonicToggleProps | undefined>;
363
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicToggleFieldComponent, never>;
364
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicToggleFieldComponent, "df-ion-toggle", never, { "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NgForgeFieldHost; inputs: {}; outputs: {}; }]>;
365
- }
366
-
367
249
  /**
368
250
  * Ionic field type definitions
369
251
  * Follows the FieldTypeDefinition interface for proper registry integration
@@ -474,40 +356,30 @@ type IonicAddonsFeature = {
474
356
  /** Register Ionic-shipped addon types (`ion-icon`, `ion-button`) standalone. */
475
357
  declare function withIonicAddons(): IonicAddonsFeature;
476
358
 
477
- /** Renderer for the `ion-button` addon type. */
478
- declare class IonicButtonAddonComponent {
479
- protected readonly action: i1.TypedNgForgeAddonAction<IonicButtonAddon>;
480
- /** Re-exposed for template binding — same signal stored on the directive. */
481
- protected readonly addon: _angular_core.Signal<IonicButtonAddon>;
482
- protected readonly label: _angular_core.Signal<_ng_forge_dynamic_forms.DynamicText | undefined>;
483
- protected readonly ariaLabel: _angular_core.Signal<_ng_forge_dynamic_forms.DynamicText | undefined>;
484
- protected readonly icon: _angular_core.Signal<string | undefined>;
485
- /** Default color is undefined so the button inherits the theme's text color
486
- * (Ionic's `medium` would force low-contrast grey, which fails WCAG on dark
487
- * surfaces). Consumers can still set `color: 'primary' | 'success' | ...`
488
- * explicitly when they want adapter-styled coloring. */
489
- protected readonly color: _angular_core.Signal<"primary" | "secondary" | "tertiary" | "success" | "warning" | "danger" | "light" | "medium" | "dark" | undefined>;
490
- protected readonly fill: _angular_core.Signal<"clear" | "outline" | "solid" | "default">;
491
- /** Icon-only when there is an icon but no label — drives the `slot` choice.
492
- * Truthy check on `label` mirrors Material's heuristic; empty-string label
493
- * is treated as "no label" so the button doesn't render an invisible text
494
- * slot beside the icon. */
495
- protected readonly iconOnly: _angular_core.Signal<boolean>;
496
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicButtonAddonComponent, never>;
497
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicButtonAddonComponent, "df-ion-button-addon", never, {}, {}, never, never, true, [{ directive: typeof i1.NgForgeAddonAction; inputs: {}; outputs: {}; }]>;
498
- }
499
-
500
- /** Renderer for the `ion-icon` addon type. */
501
- declare class IonicIconAddonComponent {
502
- readonly addon: _angular_core.InputSignal<IonicIconAddon>;
503
- /** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every type must declare it. */
504
- readonly fieldInputs: _angular_core.InputSignal<WrapperFieldInputs | undefined>;
505
- protected readonly iconName: _angular_core.Signal<string>;
506
- protected readonly ariaLabel: _angular_core.Signal<_ng_forge_dynamic_forms.DynamicText | undefined>;
507
- protected readonly hasAriaLabel: _angular_core.Signal<boolean>;
508
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicIconAddonComponent, never>;
509
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicIconAddonComponent, "df-ion-icon-addon", never, { "addon": { "alias": "addon"; "required": true; "isSignal": true; }; "fieldInputs": { "alias": "fieldInputs"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
510
- }
359
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/button`. Import it from there to use the class as a value. */
360
+ type IonicButtonFieldComponent<TEvent extends FormEvent> = IonicButtonFieldComponent$1<TEvent>;
361
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/checkbox`. Import it from there to use the class as a value. */
362
+ type IonicCheckboxFieldComponent = IonicCheckboxFieldComponent$1;
363
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/datepicker`. Import it from there to use the class as a value. */
364
+ type IonicDatepickerFieldComponent = IonicDatepickerFieldComponent$1;
365
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/input`. Import it from there to use the class as a value. */
366
+ type IonicInputFieldComponent = IonicInputFieldComponent$1;
367
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/multi-checkbox`. Import it from there to use the class as a value. */
368
+ type IonicMultiCheckboxFieldComponent = IonicMultiCheckboxFieldComponent$1;
369
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/radio`. Import it from there to use the class as a value. */
370
+ type IonicRadioFieldComponent = IonicRadioFieldComponent$1;
371
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/select`. Import it from there to use the class as a value. */
372
+ type IonicSelectFieldComponent = IonicSelectFieldComponent$1;
373
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/slider`. Import it from there to use the class as a value. */
374
+ type IonicSliderFieldComponent = IonicSliderFieldComponent$1;
375
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/textarea`. Import it from there to use the class as a value. */
376
+ type IonicTextareaFieldComponent = IonicTextareaFieldComponent$1;
377
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/toggle`. Import it from there to use the class as a value. */
378
+ type IonicToggleFieldComponent = IonicToggleFieldComponent$1;
379
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/addon-icon`. Import it from there to use the class as a value. */
380
+ type IonicIconAddonComponent = IonicIconAddonComponent$1;
381
+ /** Class type of the component in `@ng-forge/dynamic-forms-ionic/lazy/addon-button`. Import it from there to use the class as a value. */
382
+ type IonicButtonAddonComponent = IonicButtonAddonComponent$1;
511
383
 
512
- export { IONIC_FIELD_TYPES, IonicButtonAddonComponent, IonicButtonFieldComponent, IonicCheckboxFieldComponent, IonicDatepickerFieldComponent, IonicField, IonicIconAddonComponent, IonicInputFieldComponent, IonicMultiCheckboxFieldComponent, IonicRadioFieldComponent, IonicSelectFieldComponent, IonicSliderFieldComponent, IonicTextareaFieldComponent, IonicToggleFieldComponent, withIonicAddons, withIonicFields };
513
- export type { IonicAddArrayItemButtonField, IonicAddonExtensions, IonicButtonField, IonicButtonProps, IonicCheckboxField, IonicCheckboxProps, IonicDatepickerField, IonicDatepickerProps, IonicFieldType, IonicFormConfig, IonicFormProps, IonicInputAddon, IonicInputField, IonicInputProps, IonicInsertArrayItemButtonField, IonicMultiCheckboxField, IonicMultiCheckboxProps, IonicNextButtonField, IonicPopArrayItemButtonField, IonicPrependArrayItemButtonField, IonicPreviousButtonField, IonicRadioField, IonicRadioProps, IonicRemoveArrayItemButtonField, IonicSelectField, IonicSelectProps, IonicShiftArrayItemButtonField, IonicSliderField, IonicSliderProps, IonicSubmitButtonField, IonicTextareaField, IonicTextareaProps, IonicToggleField, IonicToggleProps };
384
+ export { IONIC_FIELD_TYPES, IonicField, withIonicAddons, withIonicFields };
385
+ export type { IonicAddArrayItemButtonField, IonicAddonExtensions, IonicButtonAddonComponent, IonicButtonField, IonicButtonFieldComponent, IonicButtonProps, IonicCheckboxField, IonicCheckboxFieldComponent, IonicCheckboxProps, IonicDatepickerField, IonicDatepickerFieldComponent, IonicDatepickerProps, IonicFieldType, IonicFormConfig, IonicFormProps, IonicIconAddonComponent, IonicInputAddon, IonicInputField, IonicInputFieldComponent, IonicInputProps, IonicInsertArrayItemButtonField, IonicMultiCheckboxField, IonicMultiCheckboxFieldComponent, IonicMultiCheckboxProps, IonicNextButtonField, IonicPopArrayItemButtonField, IonicPrependArrayItemButtonField, IonicPreviousButtonField, IonicRadioField, IonicRadioFieldComponent, IonicRadioProps, IonicRemoveArrayItemButtonField, IonicSelectField, IonicSelectFieldComponent, IonicSelectProps, IonicShiftArrayItemButtonField, IonicSliderField, IonicSliderFieldComponent, IonicSliderProps, IonicSubmitButtonField, IonicTextareaField, IonicTextareaFieldComponent, IonicTextareaProps, IonicToggleField, IonicToggleFieldComponent, IonicToggleProps };