@ng-forge/dynamic-forms-material 0.9.0-next.12 → 0.9.0-next.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,9 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { InjectionToken, Provider } from '@angular/core';
2
+ import { InjectionToken, Provider, WritableSignal } from '@angular/core';
3
3
  import * as _ng_forge_dynamic_forms_integration from '@ng-forge/dynamic-forms/integration';
4
4
  import { CheckboxField, DatepickerField, DatepickerProps, InputField, InputProps, MultiCheckboxField, RadioField, SelectField, SelectProps, SliderField, ButtonField, TextareaField, TextareaProps, ToggleField } from '@ng-forge/dynamic-forms/integration';
5
- import { DynamicText, CheckedFieldComponent, ValueFieldComponent, ValueType, FieldOption, FormEvent, NextPageEvent, PreviousPageEvent, AppendArrayItemEvent, ArrayAllowedChildren, PrependArrayItemEvent, InsertArrayItemEvent, RemoveAtIndexEvent, PopArrayItemEvent, ShiftArrayItemEvent, FieldTypeDefinition, NarrowFields, RegisteredFieldTypes, InferFormValue, FormConfig } from '@ng-forge/dynamic-forms';
5
+ import * as _ng_forge_dynamic_forms from '@ng-forge/dynamic-forms';
6
+ import { DynamicText, CheckedFieldComponent, ValueFieldComponent, BaseAddon, DynamicValue, AddonActionPreset, RegisteredActionRef, AddonActionHandler, TextAddon, TemplateAddon, WrapperFieldInputs, ValueType, FieldOption, FormEvent, NextPageEvent, PreviousPageEvent, AppendArrayItemEvent, ArrayAllowedChildren, PrependArrayItemEvent, InsertArrayItemEvent, RemoveAtIndexEvent, PopArrayItemEvent, ShiftArrayItemEvent, FieldTypeDefinition, NarrowFields, RegisteredFieldTypes, InferFormValue, FormConfig } from '@ng-forge/dynamic-forms';
6
7
  import { ThemePalette } from '@angular/material/core';
7
8
  import * as _angular_material_form_field from '@angular/material/form-field';
8
9
  import { MatFormFieldAppearance, SubscriptSizing, FloatLabelType } from '@angular/material/form-field';
@@ -57,6 +58,122 @@ declare class MatDatepickerFieldComponent {
57
58
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatDatepickerFieldComponent, "df-mat-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 _ng_forge_dynamic_forms_integration.NgForgeFieldHost; inputs: {}; outputs: {}; }]>;
58
59
  }
59
60
 
61
+ /**
62
+ * Decorative icon addon for Material fields.
63
+ *
64
+ * Renders `<mat-icon>{icon}</mat-icon>` using Material Icons ligatures —
65
+ * `icon: 'search'` produces `<mat-icon>search</mat-icon>`.
66
+ *
67
+ * Add `ariaLabel` for icons that convey meaning (search, error, success);
68
+ * leave it omitted for purely decorative icons (will be `aria-hidden="true"`).
69
+ */
70
+ interface MatIconAddon extends BaseAddon {
71
+ readonly kind: 'mat-icon';
72
+ /** Material Icons name (ligature, e.g., `'search'`, `'close'`). */
73
+ readonly icon: string;
74
+ /** Accessible label for icons that convey meaning. */
75
+ readonly ariaLabel?: DynamicText;
76
+ }
77
+ /**
78
+ * Common shape of every `mat-button` addon — properties that don't
79
+ * participate in either XOR axis.
80
+ */
81
+ interface MatButtonBase extends BaseAddon {
82
+ readonly kind: 'mat-button';
83
+ /** Material button colour variant. */
84
+ readonly color?: 'primary' | 'accent' | 'warn';
85
+ /** Reactive loading state — when truthy the button is disabled. */
86
+ readonly loading?: DynamicValue<boolean>;
87
+ }
88
+ /**
89
+ * Click axis — XOR enforced at type level so configurations that combine
90
+ * two click handlers (e.g., `preset` AND `actionRef`) are rejected by
91
+ * TypeScript. Runtime XOR validation stays as defence-in-depth for
92
+ * JSON-source configs that bypass the type checker.
93
+ */
94
+ type MatButtonClickPreset = {
95
+ /** Built-in preset action (e.g., `'clear'`, `'toggle-password-visibility'`). JSON-safe. */
96
+ readonly preset: AddonActionPreset;
97
+ readonly actionRef?: never;
98
+ readonly action?: never;
99
+ };
100
+ /**
101
+ * Value type for the `actionRef` slot. When no actions have been registered
102
+ * via `provideAddonActions(...)`, `RegisteredActionRef` resolves to `never` —
103
+ * which would make this variant uninhabitable and break `addon.actionRef`
104
+ * narrowing in the renderer. Fall back to `string` so the variant stays
105
+ * usable; once the user augments `DynamicFormActionRegistry`, autocomplete
106
+ * tightens to the registered keys.
107
+ */
108
+ type MatButtonActionRef = [RegisteredActionRef] extends [never] ? string : RegisteredActionRef;
109
+ type MatButtonClickActionRef = {
110
+ readonly preset?: never;
111
+ /** Reference to a handler registered via `provideAddonActions(...)`. JSON-safe. */
112
+ readonly actionRef: MatButtonActionRef;
113
+ readonly action?: never;
114
+ };
115
+ type MatButtonClickAction = {
116
+ readonly preset?: never;
117
+ readonly actionRef?: never;
118
+ /** Inline handler — code-only; dropped from JSON-derived configs. */
119
+ readonly action: AddonActionHandler;
120
+ };
121
+ type MatButtonClickNone = {
122
+ readonly preset?: never;
123
+ readonly actionRef?: never;
124
+ readonly action?: never;
125
+ };
126
+ type MatButtonClick = MatButtonClickPreset | MatButtonClickActionRef | MatButtonClickAction | MatButtonClickNone;
127
+ /**
128
+ * Content axis — XOR enforced at type level so an icon-only button is
129
+ * forced to declare `ariaLabel`. The three shapes:
130
+ *
131
+ * - `IconOnly` — just `icon`; `ariaLabel` is REQUIRED
132
+ * - `Labeled` — `label` set; `icon` and `ariaLabel` optional
133
+ * - `Decorative` — neither icon nor label
134
+ */
135
+ type MatButtonContentIconOnly = {
136
+ readonly icon: string;
137
+ readonly label?: never;
138
+ /** REQUIRED: icon-only buttons must carry an accessible label. */
139
+ readonly ariaLabel: DynamicText;
140
+ };
141
+ type MatButtonContentLabeled = {
142
+ readonly icon?: string;
143
+ readonly label: DynamicText;
144
+ readonly ariaLabel?: DynamicText;
145
+ };
146
+ type MatButtonContentDecorative = {
147
+ readonly icon?: never;
148
+ readonly label?: never;
149
+ readonly ariaLabel?: DynamicText;
150
+ };
151
+ type MatButtonContent = MatButtonContentIconOnly | MatButtonContentLabeled | MatButtonContentDecorative;
152
+ /**
153
+ * Interactive button addon for Material fields.
154
+ *
155
+ * Renders `<button mat-icon-button>` (icon-only) or `<button mat-button>`
156
+ * (labeled). Click dispatch (preset / actionRef / action precedence) lives
157
+ * on `NgForgeAddonAction`; this addon shape focuses on configuration.
158
+ *
159
+ * Type-level guarantees:
160
+ *
161
+ * - **Content axis (XOR):** `IconOnly` (icon + required ariaLabel) |
162
+ * `Labeled` (label, icon optional) | `Decorative` (neither). The IDE
163
+ * rejects icon-only configs that omit `ariaLabel`.
164
+ * - **Click axis (XOR):** exactly one of `preset` / `actionRef` / `action`,
165
+ * or none.
166
+ */
167
+ type MatButtonAddon = MatButtonBase & MatButtonContent & MatButtonClick;
168
+ /** Union of all Material-shipped addon kinds. */
169
+ type MatAddon = MatIconAddon | MatButtonAddon;
170
+ declare module '@ng-forge/dynamic-forms' {
171
+ interface DynamicFormAddonRegistry {
172
+ 'mat-icon': MatIconAddon;
173
+ 'mat-button': MatButtonAddon;
174
+ }
175
+ }
176
+
60
177
  interface MatInputProps extends InputProps {
61
178
  appearance?: MatFormFieldAppearance;
62
179
  disableRipple?: boolean;
@@ -66,20 +183,63 @@ interface MatInputProps extends InputProps {
66
183
  type?: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url';
67
184
  hint?: DynamicText;
68
185
  }
69
- type MatInputField = InputField<MatInputProps>;
186
+ /**
187
+ * Module-augmentable seam for adding custom addon kinds to `mat-input` at
188
+ * the type level. Pair with `withCustomAddon(...)` for the runtime side:
189
+ *
190
+ * ```ts
191
+ * declare module '@ng-forge/dynamic-forms-material' {
192
+ * interface MatAddonExtensions {
193
+ * 'my-rating': MyRatingAddon;
194
+ * }
195
+ * }
196
+ * ```
197
+ *
198
+ * Empty by default — the extension lookup resolves to `never` and contributes
199
+ * nothing to the union.
200
+ */
201
+ interface MatAddonExtensions {
202
+ }
203
+ type MatAddonExtension = MatAddonExtensions[keyof MatAddonExtensions];
204
+ /**
205
+ * Addon kinds accepted by `mat-input`.
206
+ *
207
+ * Material-specific kinds (`mat-icon`, `mat-button`) plus the universal
208
+ * `text` and `template` kinds. `component` is permitted at runtime via the
209
+ * broader `BaseAddon` union (and dropped in JSON-derived configs by the
210
+ * validator) but excluded here so the IDE narrows tightly to declarative
211
+ * shapes.
212
+ *
213
+ * To extend with custom kinds, augment `MatAddonExtensions`.
214
+ */
215
+ type MatInputAddon = MatIconAddon | MatButtonAddon | TextAddon | TemplateAddon | MatAddonExtension;
216
+ type MatInputField = InputField<MatInputProps> & {
217
+ addons?: ReadonlyArray<MatInputAddon>;
218
+ };
70
219
  /** @deprecated Scheduled for removal in v1. Use `injectNgForgeField<T>()` for typed access to a field component's directive instance. */
71
220
  type MatInputComponent = ValueFieldComponent<MatInputField>;
72
221
 
73
222
  declare class MatInputFieldComponent {
74
223
  private materialConfig;
75
224
  protected readonly ngf: _ng_forge_dynamic_forms_integration.TypedNgForgeField<string>;
225
+ protected readonly ngfa: _ng_forge_dynamic_forms_integration.TypedNgForgeAddons<MatInputAddon>;
76
226
  readonly props: _angular_core.InputSignal<MatInputProps | undefined>;
227
+ /**
228
+ * Wrapper-style host bag pushed by `DfFieldOutlet`. Declared at the
229
+ * component level so `setInputIfDeclared` (which uses
230
+ * `reflectComponentType`) can write it.
231
+ */
232
+ readonly fieldInputs: _angular_core.InputSignal<WrapperFieldInputs | undefined>;
233
+ /** Per-instance type override populated by `toggle-password-visibility` preset. */
234
+ private readonly typeOverride;
77
235
  readonly appearance: _angular_core.Signal<_angular_material_form_field.MatFormFieldAppearance>;
78
236
  readonly subscriptSizing: _angular_core.Signal<_angular_material_form_field.SubscriptSizing>;
79
237
  readonly floatLabel: _angular_core.Signal<_angular_material_form_field.FloatLabelType>;
80
238
  readonly hideRequiredMarker: _angular_core.Signal<boolean>;
239
+ /** Override (set by `toggle-password-visibility` preset) wins over `props().type`. */
240
+ protected readonly type: _angular_core.Signal<string>;
81
241
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatInputFieldComponent, never>;
82
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatInputFieldComponent, "df-mat-input", never, { "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof _ng_forge_dynamic_forms_integration.NgForgeFieldHost; inputs: {}; outputs: {}; }]>;
242
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatInputFieldComponent, "df-mat-input", never, { "props": { "alias": "props"; "required": false; "isSignal": true; }; "fieldInputs": { "alias": "fieldInputs"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof _ng_forge_dynamic_forms_integration.NgForgeFieldHost; inputs: {}; outputs: {}; }, { directive: typeof _ng_forge_dynamic_forms_integration.NgForgeAddons; inputs: {}; outputs: {}; }]>;
83
243
  }
84
244
 
85
245
  interface MatMultiCheckboxProps {
@@ -526,19 +686,29 @@ type MaterialConfigFeature = {
526
686
  ɵkind: 'material-config';
527
687
  ɵproviders: Provider[];
528
688
  };
529
- type MaterialFieldsWithConfig = [...MaterialFieldTypes, MaterialConfigFeature];
530
689
  /**
531
- * Configure dynamic forms with Material Design field types.
532
- * Provides all Material Design field types for use with provideDynamicForm.
690
+ * Default `withMaterialFields()` shape — field defs + the auto-included
691
+ * addons feature so `mat-icon` / `mat-button` work out of the box.
692
+ */
693
+ type MaterialFieldsWithAddons = [...MaterialFieldTypes, MaterialAddonsFeature];
694
+ type MaterialFieldsWithConfig = [...MaterialFieldTypes, MaterialAddonsFeature, MaterialConfigFeature];
695
+ /**
696
+ * Configure dynamic forms with Material Design field types, with
697
+ * Material-shipped addon kinds (`mat-icon`, `mat-button`) auto-included so
698
+ * addons work out of the box.
699
+ *
700
+ * If you want field types WITHOUT addons (rare), pass them through
701
+ * `provideDynamicForm` directly and skip this helper. If you want addons
702
+ * WITHOUT the field types (also rare), call `withMaterialAddons()` standalone.
533
703
  *
534
704
  * @param config - Optional global configuration for Material form fields
535
705
  *
536
706
  * @example
537
707
  * ```typescript
538
- * // Application-level setup
708
+ * // Application-level setup — addons (mat-icon, mat-button) ship in automatically
539
709
  * import { ApplicationConfig } from '@angular/core';
540
- * import { provideDynamicForm } from '@ng-forge/dynamic-form';
541
- * import { withMaterialFields } from '@ng-forge/dynamic-form-material';
710
+ * import { provideDynamicForm } from '@ng-forge/dynamic-forms';
711
+ * import { withMaterialFields } from '@ng-forge/dynamic-forms-material';
542
712
  *
543
713
  * export const appConfig: ApplicationConfig = {
544
714
  * providers: [
@@ -562,11 +732,100 @@ type MaterialFieldsWithConfig = [...MaterialFieldTypes, MaterialConfigFeature];
562
732
  * };
563
733
  * ```
564
734
  *
565
- * @returns Array of field type definitions and optionally a config feature
735
+ * @returns Tuple of field type definitions, the addons feature, and
736
+ * optionally a config feature.
566
737
  */
567
- declare function withMaterialFields(): MaterialFieldTypes;
738
+ declare function withMaterialFields(): MaterialFieldsWithAddons;
568
739
  declare function withMaterialFields(config: MaterialConfig): MaterialFieldsWithConfig;
569
- declare function withMaterialFields(config: MaterialConfig | undefined): MaterialFieldTypes | MaterialFieldsWithConfig;
740
+ declare function withMaterialFields(config: MaterialConfig | undefined): MaterialFieldsWithAddons | MaterialFieldsWithConfig;
741
+ /**
742
+ * Feature kind discriminant for the Material addons feature. Matches core's
743
+ * `'addons'` kind so providers flow through the standard addon-kind pipeline
744
+ * in `provideDynamicForm`.
745
+ */
746
+ type MaterialAddonsFeature = {
747
+ ɵkind: 'addons';
748
+ ɵproviders: Provider[];
749
+ };
750
+ /**
751
+ * Register Material-shipped addon kinds (`mat-icon`, `mat-button`) standalone.
752
+ *
753
+ * **Most users don't need this** — `withMaterialFields()` auto-includes
754
+ * these kinds. Call `withMaterialAddons()` directly only when you want
755
+ * Material addon kinds without the Material field types (e.g., a custom
756
+ * field set that wants to render `mat-icon` prefixes), or when you're
757
+ * stitching addons through a different DI scope.
758
+ *
759
+ * @example
760
+ * ```typescript
761
+ * // Custom field types + Material addon kinds.
762
+ * provideDynamicForm(
763
+ * ...myCustomFields(),
764
+ * withMaterialAddons(),
765
+ * );
766
+ * ```
767
+ *
768
+ * Adapter authors who need to override a kind with a customised renderer
769
+ * should call `withCustomAddon(...)` directly instead.
770
+ */
771
+ declare function withMaterialAddons(): MaterialAddonsFeature;
772
+
773
+ /**
774
+ * Renderer for the `mat-icon` addon kind.
775
+ *
776
+ * Outputs `<mat-icon>{icon}</mat-icon>` using Material Icons ligatures. The
777
+ * host is set `aria-hidden="true"` by default; if the addon supplies an
778
+ * `ariaLabel`, it is applied so the icon is announced by screen readers.
779
+ */
780
+ declare class MatIconAddonComponent {
781
+ readonly addon: _angular_core.InputSignal<MatIconAddon>;
782
+ /** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */
783
+ readonly fieldInputs: _angular_core.InputSignal<WrapperFieldInputs | undefined>;
784
+ protected readonly ariaLabel: _angular_core.Signal<_ng_forge_dynamic_forms.DynamicText | undefined>;
785
+ protected readonly hasAriaLabel: _angular_core.Signal<boolean>;
786
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatIconAddonComponent, never>;
787
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatIconAddonComponent, "df-mat-icon-addon", never, { "addon": { "alias": "addon"; "required": true; "isSignal": true; }; "fieldInputs": { "alias": "fieldInputs"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
788
+ }
789
+
790
+ /**
791
+ * Renderer for the `mat-button` addon kind.
792
+ *
793
+ * Renders `<button mat-icon-button>` when icon-only (no label), or
794
+ * `<button mat-button>` when labeled. Click dispatch (preset / actionRef /
795
+ * action precedence, multi-set warning, `disabled` / `loading` resolution)
796
+ * lives on `NgForgeAddonAction`; this component focuses on the visual layer.
797
+ */
798
+ declare class MatButtonAddonComponent {
799
+ protected readonly action: _ng_forge_dynamic_forms_integration.TypedNgForgeAddonAction<MatButtonAddon>;
800
+ /** Re-exposed for template binding — same signal stored on the directive. */
801
+ protected readonly addon: _angular_core.Signal<MatButtonAddon>;
802
+ protected readonly label: _angular_core.Signal<_ng_forge_dynamic_forms.DynamicText | undefined>;
803
+ protected readonly ariaLabel: _angular_core.Signal<_ng_forge_dynamic_forms.DynamicText | undefined>;
804
+ protected readonly isIconOnly: _angular_core.Signal<boolean>;
805
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatButtonAddonComponent, never>;
806
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatButtonAddonComponent, "df-mat-button-addon", never, {}, {}, never, never, true, [{ directive: typeof _ng_forge_dynamic_forms_integration.NgForgeAddonAction; inputs: {}; outputs: {}; }]>;
807
+ }
808
+
809
+ /**
810
+ * Per-field writable signal that overrides the input's `type` attribute.
811
+ *
812
+ * Provided at the `mat-input` field component level. The button addon's
813
+ * `'toggle-password-visibility'` preset writes to it; the field component
814
+ * reads it to compute its effective `type`.
815
+ *
816
+ * Optional from a button's perspective — when the button is hosted inside a
817
+ * field that doesn't provide this token (e.g., textarea or a future
818
+ * non-input field), the toggle preset is a no-op.
819
+ *
820
+ * @example provided per-field:
821
+ * ```typescript
822
+ * @Component({
823
+ * providers: [{ provide: MAT_INPUT_TYPE_OVERRIDE, useValue: signal(undefined) }],
824
+ * })
825
+ * class MatInputFieldComponent { ... }
826
+ * ```
827
+ */
828
+ declare const MAT_INPUT_TYPE_OVERRIDE: InjectionToken<WritableSignal<string | undefined>>;
570
829
 
571
- export { MATERIAL_CONFIG, MATERIAL_FIELD_TYPES, MatButtonFieldComponent, MatCheckboxFieldComponent, MatDatepickerFieldComponent, MatField, MatInputFieldComponent, MatMultiCheckboxFieldComponent, MatRadioFieldComponent, MatSelectFieldComponent, MatSliderFieldComponent, MatTextareaFieldComponent, MatToggleFieldComponent, withMaterialFields };
572
- export type { AddArrayItemButtonField, InsertArrayItemButtonField, MatButtonField, MatButtonProps, MatCheckboxComponent, MatCheckboxField, MatCheckboxProps, MatDatepickerComponent, MatDatepickerField, MatDatepickerProps, MatFieldType, MatFormConfig, MatFormProps, MatInputComponent, MatInputField, MatInputProps, MatMultiCheckboxComponent, MatMultiCheckboxField, MatMultiCheckboxProps, MatNextButtonField, MatPreviousButtonField, MatRadioComponent, MatRadioField, MatRadioProps, MatSelectComponent, MatSelectField, MatSelectProps, MatSliderComponent, MatSliderField, MatSliderProps, MatSubmitButtonField, MatTextareaComponent, MatTextareaField, MatTextareaProps, MatToggleComponent, MatToggleField, MatToggleProps, MaterialConfig, PopArrayItemButtonField, PrependArrayItemButtonField, RemoveArrayItemButtonField, ShiftArrayItemButtonField };
830
+ export { MATERIAL_CONFIG, MATERIAL_FIELD_TYPES, MAT_INPUT_TYPE_OVERRIDE, MatButtonAddonComponent, MatButtonFieldComponent, MatCheckboxFieldComponent, MatDatepickerFieldComponent, MatField, MatIconAddonComponent, MatInputFieldComponent, MatMultiCheckboxFieldComponent, MatRadioFieldComponent, MatSelectFieldComponent, MatSliderFieldComponent, MatTextareaFieldComponent, MatToggleFieldComponent, withMaterialAddons, withMaterialFields };
831
+ export type { AddArrayItemButtonField, InsertArrayItemButtonField, MatAddon, MatAddonExtensions, MatButtonAddon, MatButtonField, MatButtonProps, MatCheckboxComponent, MatCheckboxField, MatCheckboxProps, MatDatepickerComponent, MatDatepickerField, MatDatepickerProps, MatFieldType, MatFormConfig, MatFormProps, MatIconAddon, MatInputAddon, MatInputComponent, MatInputField, MatInputProps, MatMultiCheckboxComponent, MatMultiCheckboxField, MatMultiCheckboxProps, MatNextButtonField, MatPreviousButtonField, MatRadioComponent, MatRadioField, MatRadioProps, MatSelectComponent, MatSelectField, MatSelectProps, MatSliderComponent, MatSliderField, MatSliderProps, MatSubmitButtonField, MatTextareaComponent, MatTextareaField, MatTextareaProps, MatToggleComponent, MatToggleField, MatToggleProps, MaterialConfig, PopArrayItemButtonField, PrependArrayItemButtonField, RemoveArrayItemButtonField, ShiftArrayItemButtonField };