@ng-forge/dynamic-forms-ionic 0.9.0-next.12 → 0.9.0-next.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,111 @@
1
+ /*
2
+ * Ionic form defaults.
3
+ *
4
+ * Opinionated host-framework defaults for Ionic apps. Library SCSS uses
5
+ * `var(--df-name, structural-fallback)` for layout-essential vars so forms
6
+ * render usefully without any opt-in. These mixins layer in the rest —
7
+ * color, typography, focus accent — that an Ionic app expects.
8
+ *
9
+ * Usage (in your app's global stylesheet):
10
+ *
11
+ * @use '@ng-forge/dynamic-forms-ionic/styles/defaults' as df;
12
+ *
13
+ * :root {
14
+ * @include df.apply-ionic-form-defaults;
15
+ * }
16
+ *
17
+ * Ionic doesn't auto-style components when `.ng-invalid` is set, so error
18
+ * styling depends on the `.ng-touched` / `.ng-invalid` compat classes from
19
+ * `withLegacyStatusClasses()`. If you opt into that feature, also include
20
+ * `apply-ionic-legacy-error-styles` once at the document level — the mixin
21
+ * emits unscoped `ion-*` selectors and matches globally regardless of where
22
+ * it's included:
23
+ *
24
+ * provideDynamicForm(...withIonicFields(), withLegacyStatusClasses())
25
+ *
26
+ * @include df.apply-ionic-legacy-error-styles;
27
+ */
28
+
29
+ @mixin form-grid-defaults {
30
+ --df-grid-columns: 12;
31
+ --df-grid-gap: 0.5rem;
32
+ --df-grid-row-gap: 0.5rem;
33
+
34
+ --df-grid-gap-sm: 0.5rem;
35
+ --df-grid-gap-md: 0.5rem;
36
+ --df-grid-gap-lg: 0.5rem;
37
+ --df-grid-gap-xl: 0.5rem;
38
+
39
+ --df-grid-row-gap-sm: 0.5rem;
40
+ --df-grid-row-gap-md: 0.5rem;
41
+ --df-grid-row-gap-lg: 0.5rem;
42
+ --df-grid-row-gap-xl: 0.5rem;
43
+
44
+ --df-array-item-gap: var(--df-grid-row-gap);
45
+
46
+ --df-focus-color: var(--ion-color-primary, #3880ff);
47
+ }
48
+
49
+ @mixin form-page-defaults {
50
+ --df-page-custom-spacing: 1.5rem;
51
+ --df-page-transition-duration: 0.3s;
52
+ --df-page-transition-timing: ease-in-out;
53
+ --df-page-slide-offset: -10px;
54
+ }
55
+
56
+ @mixin form-ionic-defaults {
57
+ --df-field-gap: 0.5rem;
58
+ --df-label-font-weight: 500;
59
+ --df-label-color: inherit;
60
+ --df-hint-color: var(--ion-color-medium, #92949c);
61
+ --df-hint-font-size: 0.875rem;
62
+ --df-error-color: var(--ion-color-danger, #eb445a);
63
+ --df-error-font-size: 0.875rem;
64
+ }
65
+
66
+ @mixin apply-ionic-form-defaults {
67
+ @include form-grid-defaults;
68
+ @include form-page-defaults;
69
+ @include form-ionic-defaults;
70
+ }
71
+
72
+ // Error-state colors for Ionic components, keyed on the legacy ng-touched /
73
+ // ng-invalid classes from `withLegacyStatusClasses()`. The selectors are
74
+ // unscoped `ion-*` element matches — include once at the document level.
75
+ // Fallback values match Ionic's documented defaults so the rules still
76
+ // produce sensible colors if `--ion-color-danger` isn't defined for some
77
+ // reason (e.g. Ionic CSS not loaded yet, or themed-out).
78
+ @mixin apply-ionic-legacy-error-styles {
79
+ ion-input.ng-invalid.ng-touched,
80
+ ion-textarea.ng-invalid.ng-touched {
81
+ --highlight-color: var(--ion-color-danger, #eb445a);
82
+ --border-color: var(--ion-color-danger, #eb445a);
83
+ }
84
+
85
+ ion-select.ng-invalid.ng-touched {
86
+ --highlight-color: var(--ion-color-danger, #eb445a);
87
+ --border-color: var(--ion-color-danger, #eb445a);
88
+ }
89
+
90
+ ion-checkbox.ng-invalid.ng-touched {
91
+ --checkbox-background-checked: var(--ion-color-danger, #eb445a);
92
+ --border-color: var(--ion-color-danger, #eb445a);
93
+ --border-color-checked: var(--ion-color-danger, #eb445a);
94
+ }
95
+
96
+ ion-radio.ng-invalid.ng-touched {
97
+ --color: var(--ion-color-danger, #eb445a);
98
+ --color-checked: var(--ion-color-danger, #eb445a);
99
+ }
100
+
101
+ ion-range.ng-invalid.ng-touched {
102
+ --bar-background: var(--ion-color-danger, #eb445a);
103
+ --knob-background: var(--ion-color-danger, #eb445a);
104
+ }
105
+
106
+ ion-toggle.ng-invalid.ng-touched {
107
+ --track-background: var(--ion-color-danger-tint, #f4707d);
108
+ --track-background-checked: var(--ion-color-danger, #eb445a);
109
+ --handle-background-checked: var(--ion-color-danger-contrast, #ffffff);
110
+ }
111
+ }
@@ -1,8 +1,10 @@
1
- import { FormEvent, NextPageEvent, PreviousPageEvent, AppendArrayItemEvent, ArrayAllowedChildren, PrependArrayItemEvent, InsertArrayItemEvent, RemoveAtIndexEvent, PopArrayItemEvent, ShiftArrayItemEvent, DynamicText, CheckedFieldComponent, ValueFieldComponent, ValueType, FieldOption, FieldTypeDefinition, NarrowFields, RegisteredFieldTypes, InferFormValue, FormConfig } from '@ng-forge/dynamic-forms';
1
+ import * as _ng_forge_dynamic_forms from '@ng-forge/dynamic-forms';
2
+ import { FormEvent, NextPageEvent, PreviousPageEvent, AppendArrayItemEvent, ArrayAllowedChildren, PrependArrayItemEvent, InsertArrayItemEvent, RemoveAtIndexEvent, PopArrayItemEvent, ShiftArrayItemEvent, DynamicText, CheckedFieldComponent, ValueFieldComponent, BaseAddon, DynamicValue, AddonActionPreset, RegisteredActionRef, AddonActionHandler, TextAddon, TemplateAddon, WrapperFieldInputs, ValueType, FieldOption, FieldTypeDefinition, NarrowFields, RegisteredFieldTypes, InferFormValue, FormConfig } from '@ng-forge/dynamic-forms';
2
3
  import * as i1 from '@ng-forge/dynamic-forms/integration';
3
4
  import { ButtonField, CheckboxField, DatepickerField, DatepickerProps, InputField, InputProps, MultiCheckboxField, RadioField, SelectField, SelectProps, SliderField, TextareaField, TextareaProps, ToggleField } from '@ng-forge/dynamic-forms/integration';
4
5
  import * as _angular_core from '@angular/core';
5
- import { InjectionToken, Provider } from '@angular/core';
6
+ import { InjectionToken, Provider, WritableSignal } from '@angular/core';
7
+ import * as _ng_forge_dynamic_forms_ionic from '@ng-forge/dynamic-forms-ionic';
6
8
 
7
9
  interface IonicButtonProps {
8
10
  expand?: 'full' | 'block';
@@ -172,6 +174,145 @@ declare class IonicDatepickerFieldComponent {
172
174
  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: {}; }]>;
173
175
  }
174
176
 
177
+ /**
178
+ * Decorative icon addon for Ion fields.
179
+ *
180
+ * Renders `<ion-icon name="{icon}">` (Ionons). The `icon` string is the
181
+ * Ionons name — e.g., `'search-outline'` produces
182
+ * `<ion-icon name="search-outline">`.
183
+ *
184
+ * Add `ariaLabel` for icons that convey meaning; leave it omitted for
185
+ * purely decorative icons (will be `aria-hidden="true"`).
186
+ */
187
+ interface IonIconAddon extends BaseAddon {
188
+ readonly kind: 'ion-icon';
189
+ /** Ionons name (e.g., `'search-outline'`, `'close-outline'`). */
190
+ readonly icon: string;
191
+ /** Accessible label for icons that convey meaning. */
192
+ readonly ariaLabel?: DynamicText;
193
+ }
194
+ /**
195
+ * Ionic-supported button colour palette.
196
+ */
197
+ type IonButtonColor = 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
198
+ /**
199
+ * Ionic-supported button fill variants.
200
+ */
201
+ type IonButtonFill = 'clear' | 'outline' | 'solid' | 'default';
202
+ /**
203
+ * Common shape of every `ion-button` addon — properties that don't
204
+ * participate in either XOR axis.
205
+ */
206
+ interface IonButtonBase extends BaseAddon {
207
+ readonly kind: 'ion-button';
208
+ /** Ion button colour. */
209
+ readonly color?: IonButtonColor;
210
+ /** Ion button fill style. */
211
+ readonly fill?: IonButtonFill;
212
+ /** Reactive loading state — renders an `<ion-spinner>` when truthy. */
213
+ readonly loading?: DynamicValue<boolean>;
214
+ }
215
+ /**
216
+ * Click axis — XOR enforced at type level so configurations that combine
217
+ * two click handlers (e.g., `preset` AND `actionRef`) are rejected by
218
+ * TypeScript. The four shapes:
219
+ *
220
+ * - `Preset` — built-in preset action.
221
+ * - `ActionRef` — typed reference to a handler registered via `provideAddonActions(...)`.
222
+ * - `Action` — inline handler (code-only; dropped from JSON-derived configs).
223
+ * - `None` — decorative button with no handler.
224
+ *
225
+ * Runtime XOR validation stays as defence-in-depth for JSON-source configs
226
+ * that bypass the type checker.
227
+ */
228
+ type IonButtonClickPreset = {
229
+ /** Built-in preset action (e.g., `'clear'`, `'toggle-password-visibility'`). JSON-safe. */
230
+ readonly preset: AddonActionPreset;
231
+ readonly actionRef?: never;
232
+ readonly action?: never;
233
+ };
234
+ /**
235
+ * Value type for the `actionRef` slot. When no actions have been registered
236
+ * via `provideAddonActions(...)`, `RegisteredActionRef` resolves to `never` —
237
+ * which would make this variant uninhabitable and break `addon.actionRef`
238
+ * narrowing in the renderer. Fall back to `string` so the variant stays
239
+ * usable; once the user augments `DynamicFormActionRegistry`, autocomplete
240
+ * tightens to the registered keys.
241
+ */
242
+ type IonButtonActionRef = [RegisteredActionRef] extends [never] ? string : RegisteredActionRef;
243
+ type IonButtonClickActionRef = {
244
+ readonly preset?: never;
245
+ /** Reference to a handler registered via `provideAddonActions(...)`. JSON-safe. */
246
+ readonly actionRef: IonButtonActionRef;
247
+ readonly action?: never;
248
+ };
249
+ type IonButtonClickAction = {
250
+ readonly preset?: never;
251
+ readonly actionRef?: never;
252
+ /** Inline handler — code-only; dropped from JSON-derived configs. Matches the generic `AddonActionHandler` shape used by `provideAddonActions(...)`. */
253
+ readonly action: AddonActionHandler;
254
+ };
255
+ type IonButtonClickNone = {
256
+ readonly preset?: never;
257
+ readonly actionRef?: never;
258
+ readonly action?: never;
259
+ };
260
+ type IonButtonClick = IonButtonClickPreset | IonButtonClickActionRef | IonButtonClickAction | IonButtonClickNone;
261
+ /**
262
+ * Content axis — XOR enforced at type level so an icon-only button is
263
+ * forced to declare `ariaLabel`. The three shapes:
264
+ *
265
+ * - `IconOnly` — just `icon`; `ariaLabel` is REQUIRED
266
+ * - `Labeled` — `label` set; `icon` and `ariaLabel` optional
267
+ * - `Decorative` — neither icon nor label (e.g., custom-rendered child)
268
+ *
269
+ * Combining keys is rejected by TypeScript — `icon: 'x'` without either
270
+ * `label` or `ariaLabel` doesn't satisfy any branch.
271
+ */
272
+ type IonButtonContentIconOnly = {
273
+ readonly icon: string;
274
+ readonly label?: never;
275
+ /** REQUIRED: icon-only buttons must carry an accessible label. */
276
+ readonly ariaLabel: DynamicText;
277
+ };
278
+ type IonButtonContentLabeled = {
279
+ readonly icon?: string;
280
+ readonly label: DynamicText;
281
+ readonly ariaLabel?: DynamicText;
282
+ };
283
+ type IonButtonContentDecorative = {
284
+ readonly icon?: never;
285
+ readonly label?: never;
286
+ readonly ariaLabel?: DynamicText;
287
+ };
288
+ type IonButtonContent = IonButtonContentIconOnly | IonButtonContentLabeled | IonButtonContentDecorative;
289
+ /**
290
+ * Interactive button addon for Ion fields.
291
+ *
292
+ * Renders `<ion-button>` with optional icon (via `<ion-icon>`), label,
293
+ * colour / fill variants, and a reactive loading state (rendered as
294
+ * `<ion-spinner>`).
295
+ *
296
+ * Type-level guarantees:
297
+ *
298
+ * - **Content axis (XOR):** `IconOnly` (icon + required ariaLabel) |
299
+ * `Labeled` (label, icon optional) | `Decorative` (neither). The IDE
300
+ * rejects icon-only configs that omit `ariaLabel`.
301
+ * - **Click axis (XOR):** exactly one of `preset` / `actionRef` / `action`,
302
+ * or none. Combining two is rejected by TypeScript at the call site;
303
+ * the runtime validator still drops the addon with a clear warning when
304
+ * JSON-source configs slip a multi-set past the type checker.
305
+ */
306
+ type IonButtonAddon = IonButtonBase & IonButtonContent & IonButtonClick;
307
+ /** Union of all Ion-shipped addon kinds. */
308
+ type IonAddon = IonIconAddon | IonButtonAddon;
309
+ declare module '@ng-forge/dynamic-forms' {
310
+ interface DynamicFormAddonRegistry {
311
+ 'ion-icon': IonIconAddon;
312
+ 'ion-button': IonButtonAddon;
313
+ }
314
+ }
315
+
175
316
  interface IonicInputProps extends InputProps {
176
317
  fill?: 'solid' | 'outline';
177
318
  shape?: 'round';
@@ -182,7 +323,38 @@ interface IonicInputProps extends InputProps {
182
323
  counter?: boolean;
183
324
  clearInput?: boolean;
184
325
  }
185
- type IonicInputField = InputField<IonicInputProps>;
326
+ /**
327
+ * Module-augmentable seam for adding custom addon kinds to `ion-input` at
328
+ * the type level. Pair with `withCustomAddon(...)` for the runtime side:
329
+ *
330
+ * ```ts
331
+ * declare module '@ng-forge/dynamic-forms-ionic' {
332
+ * interface IonAddonExtensions {
333
+ * 'my-rating': MyRatingAddon;
334
+ * }
335
+ * }
336
+ * ```
337
+ *
338
+ * Empty by default — the extension lookup resolves to `never` and contributes
339
+ * nothing to the union.
340
+ */
341
+ interface IonAddonExtensions {
342
+ }
343
+ type IonAddonExtension = IonAddonExtensions[keyof IonAddonExtensions];
344
+ /**
345
+ * Addon kinds accepted by `ion-input`.
346
+ *
347
+ * Ionic-specific kinds (`ion-icon`, `ion-button`) plus the universal `text`
348
+ * and `template` kinds. `component` is permitted at runtime via the broader
349
+ * `BaseAddon` union (and dropped in JSON-derived configs by the validator)
350
+ * but excluded here so the IDE narrows tightly to declarative shapes.
351
+ *
352
+ * To extend with custom kinds, augment `IonAddonExtensions`.
353
+ */
354
+ type IonInputAddon = IonIconAddon | IonButtonAddon | TextAddon | TemplateAddon | IonAddonExtension;
355
+ type IonicInputField = InputField<IonicInputProps> & {
356
+ addons?: ReadonlyArray<IonInputAddon>;
357
+ };
186
358
  /** @deprecated Scheduled for removal in v1. Use `injectNgForgeField<T>()` for typed access to a field component's directive instance. */
187
359
  type IonicInputComponent = ValueFieldComponent<IonicInputField>;
188
360
 
@@ -190,14 +362,39 @@ declare class IonicInputFieldComponent {
190
362
  private readonly elementRef;
191
363
  private ionicConfig;
192
364
  protected readonly ngf: i1.TypedNgForgeField<string>;
365
+ protected readonly ngfa: i1.TypedNgForgeAddons<IonInputAddon>;
193
366
  readonly props: _angular_core.InputSignal<IonicInputProps | undefined>;
367
+ /**
368
+ * Wrapper-style host bag pushed by `DfFieldOutlet`. Declared at the
369
+ * component level so `setInputIfDeclared` (which uses
370
+ * `reflectComponentType`) can write it.
371
+ */
372
+ readonly fieldInputs: _angular_core.InputSignal<WrapperFieldInputs | undefined>;
373
+ /** Per-instance type override populated by `toggle-password-visibility` preset. */
374
+ private readonly typeOverride;
194
375
  protected readonly fill: _angular_core.Signal<"outline" | "solid">;
195
376
  protected readonly shape: _angular_core.Signal<"round" | undefined>;
377
+ /** Default 'stacked' (label above the input) for adapter parity with Material /
378
+ * Bootstrap / PrimeNG. Consumers can opt into Ionic's native inline 'start'
379
+ * or 'fixed' via props.labelPlacement or the IONIC_CONFIG token. */
196
380
  protected readonly labelPlacement: _angular_core.Signal<"start" | "end" | "fixed" | "stacked" | "floating">;
197
381
  protected readonly color: _angular_core.Signal<"primary" | "secondary" | "tertiary" | "success" | "warning" | "danger" | "light" | "medium" | "dark" | undefined>;
382
+ /** Override (set by `toggle-password-visibility` preset) wins over `props().type`. */
383
+ protected readonly type: _angular_core.Signal<string>;
384
+ /** Per-kind split: ion-button addons render inline via the attribute-
385
+ * selector inline component (so the slotted element is a native
386
+ * <ion-button> Ionic can style); everything else (icon/text/template/
387
+ * component kinds) goes through the universal <df-addon-slot> dispatcher
388
+ * wrapped in <span slot="start|end"> for safe shadow-DOM projection. */
389
+ protected readonly buttonPrefixAddons: _angular_core.Signal<_ng_forge_dynamic_forms_ionic.IonButtonAddon[]>;
390
+ protected readonly buttonSuffixAddons: _angular_core.Signal<_ng_forge_dynamic_forms_ionic.IonButtonAddon[]>;
391
+ protected readonly decorativePrefixAddons: _angular_core.Signal<(_ng_forge_dynamic_forms.TextAddon | _ng_forge_dynamic_forms.TemplateAddon | _ng_forge_dynamic_forms_ionic.IonIconAddon)[]>;
392
+ protected readonly decorativeSuffixAddons: _angular_core.Signal<(_ng_forge_dynamic_forms.TextAddon | _ng_forge_dynamic_forms.TemplateAddon | _ng_forge_dynamic_forms_ionic.IonIconAddon)[]>;
393
+ /** Set when the component is destroyed — guards async aria-describedby sync against teardown. */
394
+ private destroyed;
198
395
  constructor();
199
396
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonicInputFieldComponent, never>;
200
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonicInputFieldComponent, "df-ion-input", never, { "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NgForgeFieldHost; inputs: {}; outputs: {}; }]>;
397
+ 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: {}; }]>;
201
398
  }
202
399
 
203
400
  interface IonicMultiCheckboxProps {
@@ -552,19 +749,30 @@ type IonicConfigFeature = {
552
749
  ɵkind: 'ionic-config';
553
750
  ɵproviders: Provider[];
554
751
  };
555
- type IonicFieldsWithConfig = [...IonicFieldTypes, IonicConfigFeature];
556
752
  /**
557
- * Configure dynamic forms with Ionic field types.
558
- * Provides all Ionic field types for use with provideDynamicForm.
753
+ * Default `withIonicFields()` shape — field defs + the auto-included
754
+ * addons feature so `ion-icon` / `ion-button` work out of the box.
755
+ */
756
+ type IonicFieldsWithAddons = [...IonicFieldTypes, IonicAddonsFeature];
757
+ type IonicFieldsWithConfig = [...IonicFieldTypes, IonicAddonsFeature, IonicConfigFeature];
758
+ /**
759
+ * Provides Ionic field type definitions for the dynamic form system,
760
+ * with Ionic-shipped addon kinds (`ion-icon`, `ion-button`) auto-included
761
+ * so addons work out of the box.
762
+ *
763
+ * If you want field types WITHOUT addons (rare), pass them through
764
+ * `provideDynamicForm` directly and skip this helper. If you want addons
765
+ * WITHOUT the field types (also rare — e.g., adding addons to a form that
766
+ * uses custom fields), call `withIonicAddons()` standalone.
559
767
  *
560
768
  * @param config - Optional global configuration for Ionic form fields
561
769
  *
562
770
  * @example
563
771
  * ```typescript
564
- * // Application-level setup
772
+ * // Application-level setup — addons (ion-icon, ion-button) ship in automatically
565
773
  * import { ApplicationConfig } from '@angular/core';
566
- * import { provideDynamicForm } from '@ng-forge/dynamic-form';
567
- * import { withIonicFields } from '@ng-forge/dynamic-form-ionic';
774
+ * import { provideDynamicForm } from '@ng-forge/dynamic-forms';
775
+ * import { withIonicFields } from '@ng-forge/dynamic-forms-ionic';
568
776
  *
569
777
  * export const appConfig: ApplicationConfig = {
570
778
  * providers: [
@@ -588,11 +796,105 @@ type IonicFieldsWithConfig = [...IonicFieldTypes, IonicConfigFeature];
588
796
  * };
589
797
  * ```
590
798
  *
591
- * @returns Array of field type definitions and optionally a config feature
799
+ * @returns Tuple of field type definitions, the addons feature, and
800
+ * optionally a config feature.
592
801
  */
593
- declare function withIonicFields(): IonicFieldTypes;
802
+ declare function withIonicFields(): IonicFieldsWithAddons;
594
803
  declare function withIonicFields(config: IonicConfig): IonicFieldsWithConfig;
595
- declare function withIonicFields(config: IonicConfig | undefined): IonicFieldTypes | IonicFieldsWithConfig;
804
+ declare function withIonicFields(config: IonicConfig | undefined): IonicFieldsWithAddons | IonicFieldsWithConfig;
805
+ /**
806
+ * Feature kind discriminant for the Ionic addons feature. Matches core's
807
+ * `'addons'` kind so providers flow through the standard addon-kind pipeline
808
+ * in `provideDynamicForm`.
809
+ */
810
+ type IonicAddonsFeature = {
811
+ ɵkind: 'addons';
812
+ ɵproviders: Provider[];
813
+ };
814
+ /**
815
+ * Register Ionic-shipped addon kinds (`ion-icon`, `ion-button`) standalone.
816
+ *
817
+ * **Most users don't need this** — `withIonicFields()` auto-includes
818
+ * these kinds. Call `withIonicAddons()` directly only when you want
819
+ * Ionic addon kinds without the Ionic field types (e.g., a custom
820
+ * field set that wants to render `ion-icon` prefixes), or when you're
821
+ * stitching addons through a different DI scope.
822
+ *
823
+ * @example
824
+ * ```typescript
825
+ * // Custom field types + Ionic addon kinds.
826
+ * provideDynamicForm(
827
+ * ...myCustomFields(),
828
+ * withIonicAddons(),
829
+ * );
830
+ * ```
831
+ *
832
+ * Adapter authors who need to override a kind with a customised renderer
833
+ * should call `withCustomAddon(...)` directly instead.
834
+ */
835
+ declare function withIonicAddons(): IonicAddonsFeature;
836
+
837
+ /**
838
+ * Renderer for the `ion-button` addon kind.
839
+ *
840
+ * Wraps Ionic's `<ion-button>`. Click dispatch (preset / actionRef /
841
+ * action precedence, multi-set warning, `disabled` / `loading`
842
+ * resolution) lives on `NgForgeAddonAction`; this component focuses on
843
+ * the visual layer. While `action.loading()`, an `<ion-spinner>` is
844
+ * rendered in place of the icon and the button is disabled.
845
+ */
846
+ declare class IonButtonAddonComponent {
847
+ protected readonly action: i1.TypedNgForgeAddonAction<IonButtonAddon>;
848
+ /** Re-exposed for template binding — same signal stored on the directive. */
849
+ protected readonly addon: _angular_core.Signal<IonButtonAddon>;
850
+ protected readonly label: _angular_core.Signal<_ng_forge_dynamic_forms.DynamicText | undefined>;
851
+ protected readonly ariaLabel: _angular_core.Signal<_ng_forge_dynamic_forms.DynamicText | undefined>;
852
+ protected readonly icon: _angular_core.Signal<string | undefined>;
853
+ /** Default color is undefined so the button inherits the theme's text color
854
+ * (Ionic's `medium` would force low-contrast grey, which fails WCAG on dark
855
+ * surfaces). Consumers can still set `color: 'primary' | 'success' | ...`
856
+ * explicitly when they want adapter-styled coloring. */
857
+ protected readonly color: _angular_core.Signal<("primary" | "secondary" | "tertiary" | "success" | "warning" | "danger" | "light" | "medium" | "dark") | undefined>;
858
+ protected readonly fill: _angular_core.Signal<"clear" | "outline" | "solid" | "default">;
859
+ /** Icon-only when there is an icon but no label — drives the `slot` choice.
860
+ * Truthy check on `label` mirrors Material's heuristic; empty-string label
861
+ * is treated as "no label" so the button doesn't render an invisible text
862
+ * slot beside the icon. */
863
+ protected readonly iconOnly: _angular_core.Signal<boolean>;
864
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonButtonAddonComponent, never>;
865
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonButtonAddonComponent, "df-ion-button-addon", never, {}, {}, never, never, true, [{ directive: typeof i1.NgForgeAddonAction; inputs: {}; outputs: {}; }]>;
866
+ }
867
+
868
+ /**
869
+ * Renderer for the `ion-icon` addon kind.
870
+ *
871
+ * Outputs `<ion-icon [name]="icon">`. The host is set `aria-hidden="true"`
872
+ * by default; if the addon supplies an `ariaLabel`, it is applied so the
873
+ * icon is announced by screen readers.
874
+ */
875
+ declare class IonIconAddonComponent {
876
+ readonly addon: _angular_core.InputSignal<IonIconAddon>;
877
+ /** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */
878
+ readonly fieldInputs: _angular_core.InputSignal<WrapperFieldInputs | undefined>;
879
+ protected readonly iconName: _angular_core.Signal<string>;
880
+ protected readonly ariaLabel: _angular_core.Signal<_ng_forge_dynamic_forms.DynamicText | undefined>;
881
+ protected readonly hasAriaLabel: _angular_core.Signal<boolean>;
882
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<IonIconAddonComponent, never>;
883
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<IonIconAddonComponent, "df-ion-icon-addon", never, { "addon": { "alias": "addon"; "required": true; "isSignal": true; }; "fieldInputs": { "alias": "fieldInputs"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
884
+ }
885
+
886
+ /**
887
+ * Per-field writable signal that overrides the input's `type` attribute.
888
+ *
889
+ * Provided at the `ion-input` field component level. The button addon's
890
+ * `'toggle-password-visibility'` preset writes to it; the field component
891
+ * reads it to compute its effective `type`.
892
+ *
893
+ * Optional from a button's perspective — when the button is hosted inside a
894
+ * field that doesn't provide this token (e.g., textarea or a future
895
+ * non-input field), the toggle preset is a no-op.
896
+ */
897
+ declare const IONIC_INPUT_TYPE_OVERRIDE: InjectionToken<WritableSignal<string | undefined>>;
596
898
 
597
- export { IONIC_CONFIG, IONIC_FIELD_TYPES, IonicButtonFieldComponent, IonicCheckboxFieldComponent, IonicDatepickerFieldComponent, IonicField, IonicInputFieldComponent, IonicMultiCheckboxFieldComponent, IonicRadioFieldComponent, IonicSelectFieldComponent, IonicSliderFieldComponent, IonicTextareaFieldComponent, IonicToggleFieldComponent, withIonicFields };
598
- export type { AddArrayItemButtonField, InsertArrayItemButtonField, IonicButtonField, IonicButtonProps, IonicCheckboxComponent, IonicCheckboxField, IonicCheckboxProps, IonicConfig, IonicDatepickerComponent, IonicDatepickerField, IonicDatepickerProps, IonicFieldType, IonicFormConfig, IonicFormProps, IonicInputComponent, IonicInputField, IonicInputProps, IonicMultiCheckboxComponent, IonicMultiCheckboxField, IonicMultiCheckboxProps, IonicNextButtonField, IonicPreviousButtonField, IonicRadioComponent, IonicRadioField, IonicRadioProps, IonicSelectComponent, IonicSelectField, IonicSelectProps, IonicSliderComponent, IonicSliderField, IonicSliderProps, IonicSubmitButtonField, IonicTextareaComponent, IonicTextareaField, IonicTextareaProps, IonicToggleComponent, IonicToggleField, IonicToggleProps, PopArrayItemButtonField, PrependArrayItemButtonField, RemoveArrayItemButtonField, ShiftArrayItemButtonField };
899
+ export { IONIC_CONFIG, IONIC_FIELD_TYPES, IONIC_INPUT_TYPE_OVERRIDE, IonButtonAddonComponent, IonIconAddonComponent, IonicButtonFieldComponent, IonicCheckboxFieldComponent, IonicDatepickerFieldComponent, IonicField, IonicInputFieldComponent, IonicMultiCheckboxFieldComponent, IonicRadioFieldComponent, IonicSelectFieldComponent, IonicSliderFieldComponent, IonicTextareaFieldComponent, IonicToggleFieldComponent, withIonicAddons, withIonicFields };
900
+ export type { AddArrayItemButtonField, InsertArrayItemButtonField, IonAddon, IonAddonExtensions, IonButtonAddon, IonIconAddon, IonInputAddon, IonicButtonField, IonicButtonProps, IonicCheckboxComponent, IonicCheckboxField, IonicCheckboxProps, IonicConfig, IonicDatepickerComponent, IonicDatepickerField, IonicDatepickerProps, IonicFieldType, IonicFormConfig, IonicFormProps, IonicInputComponent, IonicInputField, IonicInputProps, IonicMultiCheckboxComponent, IonicMultiCheckboxField, IonicMultiCheckboxProps, IonicNextButtonField, IonicPreviousButtonField, IonicRadioComponent, IonicRadioField, IonicRadioProps, IonicSelectComponent, IonicSelectField, IonicSelectProps, IonicSliderComponent, IonicSliderField, IonicSliderProps, IonicSubmitButtonField, IonicTextareaComponent, IonicTextareaField, IonicTextareaProps, IonicToggleComponent, IonicToggleField, IonicToggleProps, PopArrayItemButtonField, PrependArrayItemButtonField, RemoveArrayItemButtonField, ShiftArrayItemButtonField };