@ng-forge/dynamic-forms-ionic 1.3.0-next.4 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -57,20 +57,25 @@ var IonicDatepickerFieldComponent = class IonicDatepickerFieldComponent {
57
57
  }
58
58
  onDateChange(event) {
59
59
  const value = event.detail.value;
60
- if (value && typeof value === "string" && value.length > 0) {
61
- const date = new Date(value);
62
- this.ngf.field()().value.set(date);
63
- } else this.ngf.field()().value.set(null);
60
+ if (Array.isArray(value)) {
61
+ this.ngf.field()().value.set(value.map((iso) => new Date(iso)));
62
+ return;
63
+ }
64
+ this.ngf.field()().value.set(typeof value === "string" && value.length > 0 ? new Date(value) : null);
64
65
  this.closeModal();
65
66
  }
67
+ valueToIso(value) {
68
+ if (!value) return void 0;
69
+ return isDateArray(value) ? value.map((d) => d.toISOString()) : value.toISOString();
70
+ }
66
71
  dateToIsoString(date) {
67
- if (!date) return void 0;
68
- return date.toISOString();
72
+ return date ? date.toISOString() : void 0;
69
73
  }
70
74
  formatDisplayDate(date) {
71
75
  if (!date) return "";
72
76
  const options = DISPLAY_FORMATS[this.props()?.presentation ?? "date"];
73
- return new Intl.DateTimeFormat(this.locale(), options).format(date);
77
+ const format = new Intl.DateTimeFormat(this.locale(), options);
78
+ return isDateArray(date) ? date.map((d) => format.format(d)).join(", ") : format.format(date);
74
79
  }
75
80
  static ɵfac = i0.ɵɵngDeclareFactory({
76
81
  minVersion: "12.0.0",
@@ -155,8 +160,11 @@ var IonicDatepickerFieldComponent = class IonicDatepickerFieldComponent {
155
160
  <ion-content>
156
161
  <ion-datetime
157
162
  [presentation]="props()?.presentation ?? 'date'"
158
- [value]="dateToIsoString(dateValue)"
163
+ [value]="valueToIso(dateValue)"
159
164
  [multiple]="props()?.multiple ?? false"
165
+ [doneText]="(props()?.doneText | dynamicText | async) || 'Done'"
166
+ [cancelText]="(props()?.cancelText | dynamicText | async) || 'Cancel'"
167
+ [size]="props()?.size ?? 'fixed'"
160
168
  [preferWheel]="props()?.preferWheel ?? false"
161
169
  [showDefaultButtons]="props()?.showDefaultButtons ?? false"
162
170
  [showDefaultTitle]="props()?.showDefaultTitle ?? false"
@@ -417,8 +425,11 @@ i0.ɵɵngDeclareClassMetadata({
417
425
  <ion-content>
418
426
  <ion-datetime
419
427
  [presentation]="props()?.presentation ?? 'date'"
420
- [value]="dateToIsoString(dateValue)"
428
+ [value]="valueToIso(dateValue)"
421
429
  [multiple]="props()?.multiple ?? false"
430
+ [doneText]="(props()?.doneText | dynamicText | async) || 'Done'"
431
+ [cancelText]="(props()?.cancelText | dynamicText | async) || 'Cancel'"
432
+ [size]="props()?.size ?? 'fixed'"
422
433
  [preferWheel]="props()?.preferWheel ?? false"
423
434
  [showDefaultButtons]="props()?.showDefaultButtons ?? false"
424
435
  [showDefaultTitle]="props()?.showDefaultTitle ?? false"
@@ -474,6 +485,9 @@ i0.ɵɵngDeclareClassMetadata({
474
485
  }]
475
486
  }
476
487
  });
488
+ function isDateArray(value) {
489
+ return Array.isArray(value);
490
+ }
477
491
  export { IonicDatepickerFieldComponent };
478
492
 
479
493
  //# sourceMappingURL=ng-forge-dynamic-forms-ionic-lazy-datepicker.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-ionic-lazy-datepicker.mjs","names":[],"sources":["../../../../packages/dynamic-forms-ionic/src/lib/fields/datepicker/ionic-datepicker.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, 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';\n\nconst TIME = { hour: 'numeric', minute: '2-digit' } as const;\nconst DATE = { month: 'short', day: 'numeric', year: 'numeric' } as const;\n\nconst DISPLAY_FORMATS = {\n date: DATE,\n 'date-time': { ...DATE, ...TIME },\n 'time-date': { ...DATE, ...TIME },\n time: TIME,\n month: { month: 'long', year: 'numeric' },\n 'month-year': { month: 'short', year: 'numeric' },\n year: { year: 'numeric' },\n} as const satisfies Record<NonNullable<IonicDatepickerProps['presentation']>, Intl.DateTimeFormatOptions>;\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 [locale]=\"locale() ?? 'default'\"\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 /** Canonical locale tag, or undefined (browser locale) when unset or malformed. */\n protected readonly locale = computed(() => {\n const locale = this.props()?.locale;\n try {\n return locale ? Intl.getCanonicalLocales(locale)[0] : undefined;\n } catch {\n return undefined;\n }\n });\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 const options = DISPLAY_FORMATS[this.props()?.presentation ?? 'date'];\n return new Intl.DateTimeFormat(this.locale(), options).format(date);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-ionic-lazy-datepicker.mjs","names":[],"sources":["../../../../packages/dynamic-forms-ionic/src/lib/fields/datepicker/ionic-datepicker.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, 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';\n\nconst TIME = { hour: 'numeric', minute: '2-digit' } as const;\nconst DATE = { month: 'short', day: 'numeric', year: 'numeric' } as const;\n\nconst DISPLAY_FORMATS = {\n date: DATE,\n 'date-time': { ...DATE, ...TIME },\n 'time-date': { ...DATE, ...TIME },\n time: TIME,\n month: { month: 'long', year: 'numeric' },\n 'month-year': { month: 'short', year: 'numeric' },\n year: { year: 'numeric' },\n} as const satisfies Record<NonNullable<IonicDatepickerProps['presentation']>, Intl.DateTimeFormatOptions>;\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]=\"valueToIso(dateValue)\"\n [multiple]=\"props()?.multiple ?? false\"\n [doneText]=\"(props()?.doneText | dynamicText | async) || 'Done'\"\n [cancelText]=\"(props()?.cancelText | dynamicText | async) || 'Cancel'\"\n [size]=\"props()?.size ?? 'fixed'\"\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 [locale]=\"locale() ?? 'default'\"\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 | readonly 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 /** Canonical locale tag, or undefined (browser locale) when unset or malformed. */\n protected readonly locale = computed(() => {\n const locale = this.props()?.locale;\n try {\n return locale ? Intl.getCanonicalLocales(locale)[0] : undefined;\n } catch {\n return undefined;\n }\n });\n\n openModal() {\n this.isModalOpen.set(true);\n }\n\n closeModal() {\n this.isModalOpen.set(false);\n }\n\n onDateChange(event: CustomEvent) {\n // ion-datetime emits ISO 8601 strings (an array in multiple mode); store Date values.\n const value: unknown = event.detail.value;\n if (Array.isArray(value)) {\n this.ngf\n .field()()\n .value.set(value.map((iso: string) => new Date(iso)));\n // Keep the picker open so more dates can be chosen.\n return;\n }\n this.ngf\n .field()()\n .value.set(typeof value === 'string' && value.length > 0 ? new Date(value) : null);\n this.closeModal();\n }\n\n /** The field value as ion-datetime expects it: an ISO string, or an array of them in multiple mode. */\n valueToIso(value: Date | readonly Date[] | null | undefined): string | string[] | undefined {\n if (!value) return undefined;\n return isDateArray(value) ? value.map((d) => d.toISOString()) : value.toISOString();\n }\n\n dateToIsoString(date: Date | null | undefined): string | undefined {\n return date ? date.toISOString() : undefined;\n }\n\n formatDisplayDate(date: Date | readonly Date[] | null | undefined): string {\n if (!date) return '';\n const options = DISPLAY_FORMATS[this.props()?.presentation ?? 'date'];\n const format = new Intl.DateTimeFormat(this.locale(), options);\n return isDateArray(date) ? date.map((d) => format.format(d)).join(', ') : format.format(date);\n }\n}\n\nfunction isDateArray(value: Date | readonly Date[]): value is readonly Date[] {\n return Array.isArray(value);\n}\n"],"mappings":"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"}
@@ -136,6 +136,10 @@ var IonicInputFieldComponent = class IonicInputFieldComponent {
136
136
  </ion-input>
137
137
  @if (ngf.errorsToDisplay()[0]; as error) {
138
138
  <ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
139
+ } @else if (props()?.errorText && f().invalid() && f().touched()) {
140
+ <ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{
141
+ props()?.errorText | dynamicText | async
142
+ }}</ion-note>
139
143
  }
140
144
  `,
141
145
  isInline: true,
@@ -294,6 +298,10 @@ i0.ɵɵngDeclareClassMetadata({
294
298
  </ion-input>
295
299
  @if (ngf.errorsToDisplay()[0]; as error) {
296
300
  <ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
301
+ } @else if (props()?.errorText && f().invalid() && f().touched()) {
302
+ <ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{
303
+ props()?.errorText | dynamicText | async
304
+ }}</ion-note>
297
305
  }
298
306
  `,
299
307
  changeDetection: ChangeDetectionStrategy.OnPush,
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-ionic-lazy-input.mjs","names":[],"sources":["../../../../packages/dynamic-forms-ionic/src/lib/fields/input/ionic-input.component.ts"],"sourcesContent":["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"],"mappings":"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"}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-ionic-lazy-input.mjs","names":[],"sources":["../../../../packages/dynamic-forms-ionic/src/lib/fields/input/ionic-input.component.ts"],"sourcesContent":["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 } @else if (props()?.errorText && f().invalid() && f().touched()) {\n <ion-note color=\"danger\" class=\"df-ion-error\" [id]=\"ngf.errorId()\" role=\"alert\">{{\n props()?.errorText | dynamicText | async\n }}</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"],"mappings":"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"}
@@ -57,8 +57,8 @@ var IonicSelectFieldComponent = class IonicSelectFieldComponent {
57
57
  [compareWith]="props()?.compareWith ?? defaultCompare"
58
58
  [interface]="props()?.interface ?? 'alert'"
59
59
  [interfaceOptions]="props()?.interfaceOptions ?? {}"
60
- [cancelText]="props()?.cancelText ?? 'Cancel'"
61
- [okText]="props()?.okText ?? 'OK'"
60
+ [cancelText]="(props()?.cancelText | dynamicText | async) || 'Cancel'"
61
+ [okText]="(props()?.okText | dynamicText | async) || 'OK'"
62
62
  [color]="props()?.color"
63
63
  [fill]="props()?.fill ?? 'outline'"
64
64
  [shape]="props()?.shape"
@@ -181,8 +181,8 @@ i0.ɵɵngDeclareClassMetadata({
181
181
  [compareWith]="props()?.compareWith ?? defaultCompare"
182
182
  [interface]="props()?.interface ?? 'alert'"
183
183
  [interfaceOptions]="props()?.interfaceOptions ?? {}"
184
- [cancelText]="props()?.cancelText ?? 'Cancel'"
185
- [okText]="props()?.okText ?? 'OK'"
184
+ [cancelText]="(props()?.cancelText | dynamicText | async) || 'Cancel'"
185
+ [okText]="(props()?.okText | dynamicText | async) || 'OK'"
186
186
  [color]="props()?.color"
187
187
  [fill]="props()?.fill ?? 'outline'"
188
188
  [shape]="props()?.shape"
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-ionic-lazy-select.mjs","names":[],"sources":["../../../../packages/dynamic-forms-ionic/src/lib/fields/select/ionic-select.component.ts"],"sourcesContent":["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"],"mappings":";;;;;;;AAyDA,IAAqB,4BAArB,MAAqB,0BAAyB;CACzB,MAAM,mBAAkB;CAElC,UAAU,MAAgC,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAC7C,QAAQ,MAAyB,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAE1C,iBAAiB,OAAO;CANL,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAyB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAzB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAyB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,gBAAA,CAAA,EAAA,WAAA,GAAA,iBAAA,CAAA;EAAA,UAAA;EAAA,UA5ClC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCT,UAAA;EAAA,QAAA,CAAA,mfAAA,2CAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MAnCS;IAAS,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAe,UAAA;IAAA,QAAA,CAAA,YAAA,OAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAO,UAAA;IAAA,QAAA,CAAA,SAAA,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAS,UAAA;IAAA,QAAA,CAAA,WAAA;IAAA,UAAA,CAAA,WAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAA8B;IAAc,UAAA;IAAA,QAAA,CAAA,gBAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAA1C;IAAe,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAS,MAAA;GAAA;EAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AA8CjE,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAyB,YAAA,CAAA;EAhD7C,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAe,SAChB;IAAC;IAAW;IAAiB;IAAS;IAAW;IAAiB;IAAW;GAAc;GAAC,gBACrF,CAAC,gBAAgB;GAAC,UACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCT,iBACgB,wBAAwB;GAAM,QAAA,CAAA,mfAAA,2CAAA;EAAA,CAAA"}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-ionic-lazy-select.mjs","names":[],"sources":["../../../../packages/dynamic-forms-ionic/src/lib/fields/select/ionic-select.component.ts"],"sourcesContent":["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 | dynamicText | async) || 'Cancel'\"\n [okText]=\"(props()?.okText | dynamicText | async) || '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"],"mappings":";;;;;;;AAyDA,IAAqB,4BAArB,MAAqB,0BAAyB;CACzB,MAAM,mBAAkB;CAElC,UAAU,MAAgC,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAC7C,QAAQ,MAAyB,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAE1C,iBAAiB,OAAO;CANL,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAyB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAzB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAyB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,gBAAA,CAAA,EAAA,WAAA,GAAA,iBAAA,CAAA;EAAA,UAAA;EAAA,UA5ClC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCT,UAAA;EAAA,QAAA,CAAA,mfAAA,2CAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MAnCS;IAAS,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAe,UAAA;IAAA,QAAA,CAAA,YAAA,OAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAO,UAAA;IAAA,QAAA,CAAA,SAAA,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAS,UAAA;IAAA,QAAA,CAAA,WAAA;IAAA,UAAA,CAAA,WAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAA8B;IAAc,UAAA;IAAA,QAAA,CAAA,gBAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAA1C;IAAe,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAS,MAAA;GAAA;EAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AA8CjE,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAyB,YAAA,CAAA;EAhD7C,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAe,SAChB;IAAC;IAAW;IAAiB;IAAS;IAAW;IAAiB;IAAW;GAAc;GAAC,gBACrF,CAAC,gBAAgB;GAAC,UACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCT,iBACgB,wBAAwB;GAAM,QAAA,CAAA,mfAAA,2CAAA;EAAA,CAAA"}
@@ -70,6 +70,10 @@ var IonicTextareaFieldComponent = class IonicTextareaFieldComponent {
70
70
  />
71
71
  @if (ngf.errorsToDisplay()[0]; as error) {
72
72
  <ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
73
+ } @else if (props()?.errorText && f().invalid() && f().touched()) {
74
+ <ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{
75
+ props()?.errorText | dynamicText | async
76
+ }}</ion-note>
73
77
  }
74
78
  `,
75
79
  isInline: true,
@@ -187,6 +191,10 @@ i0.ɵɵngDeclareClassMetadata({
187
191
  />
188
192
  @if (ngf.errorsToDisplay()[0]; as error) {
189
193
  <ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
194
+ } @else if (props()?.errorText && f().invalid() && f().touched()) {
195
+ <ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{
196
+ props()?.errorText | dynamicText | async
197
+ }}</ion-note>
190
198
  }
191
199
  `,
192
200
  changeDetection: ChangeDetectionStrategy.OnPush,
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-ionic-lazy-textarea.mjs","names":[],"sources":["../../../../packages/dynamic-forms-ionic/src/lib/fields/textarea/ionic-textarea.component.ts"],"sourcesContent":["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"],"mappings":";;;;;;;;AAkDA,IAAqB,8BAArB,MAAqB,4BAA2B;CAC7B,aAAa,OAAO,UAAuB;CAEzC,MAAM,mBAAkB;CAElC,QAAQ,MAA2B,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAE5C,cAAA;EAIE,eAAe,CAAC,KAAK,IAAI,eAAe,IAAI,CAAC,iBAAgB;GAC3D,qBAAoB;IAClB,MAAM,cAAc,KAAK,WAAW,cAAc,cAAc,cAAc;IAC9E,IAAI,aAAa,iBACf,YAAY,gBAAe,CAAE,CAAC,MAAM,eAAc;KAChD,IAAI,CAAC,YAAY;KACjB,IAAI,aACF,WAAW,aAAa,oBAAoB,WAAW;UAEvD,WAAW,gBAAgB,kBAAkB;IAEjD,CAAC;GAEL,CAAC;EACH,CAAC;CACH;CA1BmB,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA2B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA3B,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAA2B,cAAA;EAAA,UAAA;EAAA,QAAA,EAAA,OAAA;GAAA,mBAAA;GAAA,YAAA;GAAA,UAAA;GAAA,YAAA;GAAA,mBAAA;EAAA,EAAA;EAAA,gBAAA,CAAA,EAAA,WAAA,GAAA,iBAAA,CAAA;EAAA,UAAA;EAAA,UArCpC;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BT,UAAA;EAAA,QAAA,CAAA,mfAAA,2CAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MA5BS;IAAW,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAO,UAAA;IAAA,QAAA,CAAA,SAAA,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAS,UAAA;IAAA,QAAA,CAAA,WAAA;IAAA,UAAA,CAAA,WAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAA8B;IAAc,UAAA;IAAA,QAAA,CAAA,gBAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAA1C;IAAe,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAS,MAAA;GAAA;EAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAuClD,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA2B,YAAA,CAAA;EAzC/C,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAiB,SAClB;IAAC;IAAa;IAAS;IAAW;IAAiB;IAAW;GAAc;GAAC,gBACtE,CAAC,gBAAgB;GAAC,UACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BT,iBACgB,wBAAwB;GAAM,QAAA,CAAA,mfAAA,2CAAA;EAAA,CAAA"}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-ionic-lazy-textarea.mjs","names":[],"sources":["../../../../packages/dynamic-forms-ionic/src/lib/fields/textarea/ionic-textarea.component.ts"],"sourcesContent":["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 } @else if (props()?.errorText && f().invalid() && f().touched()) {\n <ion-note color=\"danger\" class=\"df-ion-error\" [id]=\"ngf.errorId()\" role=\"alert\">{{\n props()?.errorText | dynamicText | async\n }}</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"],"mappings":";;;;;;;;AAsDA,IAAqB,8BAArB,MAAqB,4BAA2B;CAC7B,aAAa,OAAO,UAAuB;CAEzC,MAAM,mBAAkB;CAElC,QAAQ,MAA2B,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAE5C,cAAA;EAIE,eAAe,CAAC,KAAK,IAAI,eAAe,IAAI,CAAC,iBAAgB;GAC3D,qBAAoB;IAClB,MAAM,cAAc,KAAK,WAAW,cAAc,cAAc,cAAc;IAC9E,IAAI,aAAa,iBACf,YAAY,gBAAe,CAAE,CAAC,MAAM,eAAc;KAChD,IAAI,CAAC,YAAY;KACjB,IAAI,aACF,WAAW,aAAa,oBAAoB,WAAW;UAEvD,WAAW,gBAAgB,kBAAkB;IAEjD,CAAC;GAEL,CAAC;EACH,CAAC;CACH;CA1BmB,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA2B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA3B,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAA2B,cAAA;EAAA,UAAA;EAAA,QAAA,EAAA,OAAA;GAAA,mBAAA;GAAA,YAAA;GAAA,UAAA;GAAA,YAAA;GAAA,mBAAA;EAAA,EAAA;EAAA,gBAAA,CAAA,EAAA,WAAA,GAAA,iBAAA,CAAA;EAAA,UAAA;EAAA,UAzCpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8BT,UAAA;EAAA,QAAA,CAAA,mfAAA,2CAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MAhCS;IAAW,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAO,UAAA;IAAA,QAAA,CAAA,SAAA,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAS,UAAA;IAAA,QAAA,CAAA,WAAA;IAAA,UAAA,CAAA,WAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAA8B;IAAc,UAAA;IAAA,QAAA,CAAA,gBAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAA1C;IAAe,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAS,MAAA;GAAA;EAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AA2ClD,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA2B,YAAA,CAAA;EA7C/C,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAiB,SAClB;IAAC;IAAa;IAAS;IAAW;IAAiB;IAAW;GAAc;GAAC,gBACtE,CAAC,gBAAgB;GAAC,UACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BT,iBACgB,wBAAwB;GAAM,QAAA,CAAA,mfAAA,2CAAA;EAAA,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-forge/dynamic-forms-ionic",
3
- "version": "1.3.0-next.4",
3
+ "version": "1.3.0",
4
4
  "description": "Ionic integration for @ng-forge/dynamic-forms. Pre-built Ionic form components for mobile and desktop.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -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.3.0-next.4",
98
+ "@ng-forge/dynamic-forms": "~1.3.0",
99
99
  "rxjs": ">=7.0.0"
100
100
  },
101
101
  "dependencies": {
@@ -5,7 +5,7 @@ import * as i0 from "@angular/core";
5
5
  interface IonicCheckboxProps {
6
6
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
7
7
  justify?: 'start' | 'end' | 'space-between';
8
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
8
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
9
9
  indeterminate?: boolean;
10
10
  hint?: DynamicText;
11
11
  }
@@ -10,17 +10,17 @@ interface IonicDatepickerProps extends DatepickerProps {
10
10
  showDefaultTitle?: boolean;
11
11
  showDefaultTimeLabel?: boolean;
12
12
  showClearButton?: boolean;
13
- doneText?: string;
14
- cancelText?: string;
13
+ doneText?: DynamicText;
14
+ cancelText?: DynamicText;
15
15
  size?: 'cover' | 'fixed';
16
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
16
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
17
17
  hint?: DynamicText;
18
18
  /** BCP 47 locale for the picker and the displayed value. Defaults to the browser locale. */
19
19
  locale?: string;
20
20
  }
21
21
  type IonicDatepickerField = DatepickerField<IonicDatepickerProps>;
22
22
  declare class IonicDatepickerFieldComponent {
23
- protected readonly ngf: import("@ng-forge/dynamic-forms/integration").TypedNgForgeField<Date | null>;
23
+ protected readonly ngf: import("@ng-forge/dynamic-forms/integration").TypedNgForgeField<Date | readonly Date[] | null>;
24
24
  readonly minDate: import("@angular/core").InputSignal<Date | null>;
25
25
  readonly maxDate: import("@angular/core").InputSignal<Date | null>;
26
26
  readonly startAt: import("@angular/core").InputSignal<Date | null>;
@@ -31,8 +31,10 @@ declare class IonicDatepickerFieldComponent {
31
31
  openModal(): void;
32
32
  closeModal(): void;
33
33
  onDateChange(event: CustomEvent): void;
34
+ /** The field value as ion-datetime expects it: an ISO string, or an array of them in multiple mode. */
35
+ valueToIso(value: Date | readonly Date[] | null | undefined): string | string[] | undefined;
34
36
  dateToIsoString(date: Date | null | undefined): string | undefined;
35
- formatDisplayDate(date: Date | null | undefined): string;
37
+ formatDisplayDate(date: Date | readonly Date[] | null | undefined): string;
36
38
  static ɵfac: i0.ɵɵFactoryDeclaration<IonicDatepickerFieldComponent, never>;
37
39
  static ɵcmp: i0.ɵɵComponentDeclaration<IonicDatepickerFieldComponent, "df-ion-datepicker", never, {
38
40
  "minDate": {
@@ -5,7 +5,7 @@ import * as i0 from "@angular/core";
5
5
  interface IonicMultiCheckboxProps {
6
6
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
7
7
  justify?: 'start' | 'end' | 'space-between';
8
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
8
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
9
9
  hint?: DynamicText;
10
10
  }
11
11
  type IonicMultiCheckboxField<T> = MultiCheckboxField<T, IonicMultiCheckboxProps>;
@@ -5,7 +5,7 @@ import * as i0 from "@angular/core";
5
5
  interface IonicRadioProps {
6
6
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
7
7
  justify?: 'start' | 'end' | 'space-between';
8
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
8
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
9
9
  compareWith?: (o1: ValueType, o2: ValueType) => boolean;
10
10
  hint?: DynamicText;
11
11
  }
@@ -6,12 +6,12 @@ interface IonicSelectProps extends SelectProps {
6
6
  multiple?: boolean;
7
7
  interface?: 'action-sheet' | 'popover' | 'alert';
8
8
  interfaceOptions?: unknown;
9
- cancelText?: string;
10
- okText?: string;
9
+ cancelText?: DynamicText;
10
+ okText?: DynamicText;
11
11
  fill?: 'solid' | 'outline';
12
12
  shape?: 'round';
13
13
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked' | 'floating';
14
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
14
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
15
15
  compareWith?: (o1: ValueType, o2: ValueType) => boolean;
16
16
  hint?: DynamicText;
17
17
  }
@@ -23,7 +23,7 @@ interface IonicSliderProps {
23
23
  pinFormatter?: (value: number) => string | number;
24
24
  ticks?: boolean;
25
25
  snaps?: boolean;
26
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
26
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
27
27
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
28
28
  hint?: DynamicText;
29
29
  }
@@ -6,7 +6,7 @@ import { FormCheckboxControl } from "@angular/forms/signals";
6
6
  interface IonicToggleProps {
7
7
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
8
8
  justify?: 'start' | 'end' | 'space-between';
9
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
9
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
10
10
  enableOnOffLabels?: boolean;
11
11
  hint?: DynamicText;
12
12
  }
@@ -119,7 +119,7 @@ type IonicShiftArrayItemButtonField = Omit<IonicButtonField<ShiftArrayItemEvent>
119
119
  interface IonicCheckboxProps {
120
120
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
121
121
  justify?: 'start' | 'end' | 'space-between';
122
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
122
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
123
123
  indeterminate?: boolean;
124
124
  hint?: DynamicText;
125
125
  }
@@ -132,10 +132,10 @@ interface IonicDatepickerProps extends DatepickerProps {
132
132
  showDefaultTitle?: boolean;
133
133
  showDefaultTimeLabel?: boolean;
134
134
  showClearButton?: boolean;
135
- doneText?: string;
136
- cancelText?: string;
135
+ doneText?: DynamicText;
136
+ cancelText?: DynamicText;
137
137
  size?: 'cover' | 'fixed';
138
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
138
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
139
139
  hint?: DynamicText;
140
140
  /** BCP 47 locale for the picker and the displayed value. Defaults to the browser locale. */
141
141
  locale?: string;
@@ -165,14 +165,14 @@ type IonicInputField = InputField<IonicInputProps> & {
165
165
  interface IonicMultiCheckboxProps {
166
166
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
167
167
  justify?: 'start' | 'end' | 'space-between';
168
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
168
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
169
169
  hint?: DynamicText;
170
170
  }
171
171
  type IonicMultiCheckboxField<T> = MultiCheckboxField<T, IonicMultiCheckboxProps>;
172
172
  interface IonicRadioProps {
173
173
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
174
174
  justify?: 'start' | 'end' | 'space-between';
175
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
175
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
176
176
  compareWith?: (o1: ValueType, o2: ValueType) => boolean;
177
177
  hint?: DynamicText;
178
178
  }
@@ -181,12 +181,12 @@ interface IonicSelectProps extends SelectProps {
181
181
  multiple?: boolean;
182
182
  interface?: 'action-sheet' | 'popover' | 'alert';
183
183
  interfaceOptions?: unknown;
184
- cancelText?: string;
185
- okText?: string;
184
+ cancelText?: DynamicText;
185
+ okText?: DynamicText;
186
186
  fill?: 'solid' | 'outline';
187
187
  shape?: 'round';
188
188
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked' | 'floating';
189
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
189
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
190
190
  compareWith?: (o1: ValueType, o2: ValueType) => boolean;
191
191
  hint?: DynamicText;
192
192
  }
@@ -212,7 +212,7 @@ interface IonicSliderProps {
212
212
  pinFormatter?: (value: number) => string | number;
213
213
  ticks?: boolean;
214
214
  snaps?: boolean;
215
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
215
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
216
216
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
217
217
  hint?: DynamicText;
218
218
  }
@@ -231,7 +231,7 @@ type IonicTextareaField = TextareaField<IonicTextareaProps>;
231
231
  interface IonicToggleProps {
232
232
  labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';
233
233
  justify?: 'start' | 'end' | 'space-between';
234
- color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger';
234
+ color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
235
235
  enableOnOffLabels?: boolean;
236
236
  hint?: DynamicText;
237
237
  }