@ng-forge/dynamic-forms-material 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-forge/dynamic-forms-material",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Angular Material integration for @ng-forge/dynamic-forms. Pre-built Material Design form components.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -23,16 +23,16 @@
23
23
  "form-builder",
24
24
  "ng-forge"
25
25
  ],
26
- "sideEffects": false,
26
+ "sideEffects": true,
27
27
  "engines": {
28
- "node": ">=18"
28
+ "node": ">=20"
29
29
  },
30
30
  "peerDependencies": {
31
- "@angular/common": ">=21.0.7",
32
- "@angular/core": ">=21.0.7",
33
- "@angular/forms": ">=21.0.7",
34
- "@angular/material": ">=21.0.5",
35
- "@ng-forge/dynamic-forms": "~0.3.0",
31
+ "@angular/common": "~21.1.0",
32
+ "@angular/core": "~21.1.0",
33
+ "@angular/forms": "~21.1.0",
34
+ "@angular/material": "~21.1.0",
35
+ "@ng-forge/dynamic-forms": "~0.4.0",
36
36
  "rxjs": ">=7.0.0"
37
37
  },
38
38
  "module": "fesm2022/ng-forge-dynamic-forms-material.mjs",
@@ -3,7 +3,7 @@ import { CheckboxField, DatepickerField, DatepickerProps, InputMeta, InputField,
3
3
  import * as _angular_core from '@angular/core';
4
4
  import { InjectionToken, Provider } from '@angular/core';
5
5
  import { FieldTree } from '@angular/forms/signals';
6
- import { DynamicText, CheckedFieldComponent, FieldMeta, ValidationMessages, ValueFieldComponent, ValueType, FieldOption, FormEvent, FieldDef, LogicConfig, FieldComponent, FormEventConstructor, ArrayItemContext, FieldTypeDefinition } from '@ng-forge/dynamic-forms';
6
+ import { DynamicText, CheckedFieldComponent, FieldMeta, ValidationMessages, ValueFieldComponent, ValueType, FieldOption, FormEvent, FieldDef, LogicConfig, FieldComponent, FormEventConstructor, ArrayItemContext, FieldTypeDefinition, NarrowFields, RegisteredFieldTypes, InferFormValue, FormConfig } from '@ng-forge/dynamic-forms';
7
7
  import { ThemePalette } from '@angular/material/core';
8
8
  import * as _angular_material_form_field from '@angular/material/form-field';
9
9
  import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field';
@@ -45,7 +45,7 @@ declare class MatCheckboxFieldComponent implements MatCheckboxComponent {
45
45
  /** aria-required: true if field is required, null otherwise (to remove attribute) */
46
46
  protected readonly ariaRequired: _angular_core.Signal<true | null>;
47
47
  /** aria-describedby: links to hint and error messages for screen readers */
48
- protected readonly ariaDescribedBy: _angular_core.Signal<string>;
48
+ protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
49
49
  /**
50
50
  * Workaround: Angular Material's MatCheckbox does NOT set aria-required on its internal
51
51
  * input element when [required] is passed, even though it sets the native required attribute.
@@ -53,8 +53,17 @@ declare class MatCheckboxFieldComponent implements MatCheckboxComponent {
53
53
  *
54
54
  * Bug: MatCheckbox sets `required` attribute but not `aria-required` for screen readers.
55
55
  * @see https://github.com/angular/components/issues/XXXXX (TODO: file issue)
56
+ *
57
+ * Uses afterRenderEffect to ensure DOM is ready before manipulating attributes.
56
58
  */
57
59
  private readonly syncAriaRequiredToDom;
60
+ /**
61
+ * Workaround: Angular Material's MatCheckbox does NOT propagate aria-describedby to its internal
62
+ * input element. This effect imperatively sets/removes aria-describedby on the internal input.
63
+ *
64
+ * Uses afterRenderEffect to ensure DOM is ready before querying internal elements.
65
+ */
66
+ private readonly syncAriaDescribedByToDom;
58
67
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatCheckboxFieldComponent, never>;
59
68
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatCheckboxFieldComponent, "df-mat-checkbox", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
60
69
  }
@@ -183,22 +192,24 @@ interface MatMultiCheckboxProps {
183
192
  color?: ThemePalette;
184
193
  }
185
194
  type MatMultiCheckboxField<T> = MultiCheckboxField<T, MatMultiCheckboxProps>;
186
- type MatMultiCheckboxComponent<T> = ValueFieldComponent<MatMultiCheckboxField<T>>;
195
+ type MatMultiCheckboxComponent = ValueFieldComponent<MatMultiCheckboxField<ValueType>>;
187
196
 
188
- declare class MatMultiCheckboxFieldComponent<T extends ValueType> implements MatMultiCheckboxComponent<T> {
197
+ declare class MatMultiCheckboxFieldComponent implements MatMultiCheckboxComponent {
189
198
  private readonly elementRef;
190
- readonly field: _angular_core.InputSignal<FieldTree<T[]>>;
199
+ readonly field: _angular_core.InputSignal<FieldTree<ValueType[]>>;
191
200
  readonly key: _angular_core.InputSignal<string>;
192
201
  readonly label: _angular_core.InputSignal<DynamicText | undefined>;
193
202
  readonly placeholder: _angular_core.InputSignal<DynamicText | undefined>;
194
203
  readonly className: _angular_core.InputSignal<string>;
195
204
  readonly tabIndex: _angular_core.InputSignal<number | undefined>;
196
- readonly options: _angular_core.InputSignal<FieldOption<T>[]>;
205
+ readonly options: _angular_core.InputSignal<FieldOption<ValueType>[]>;
197
206
  readonly props: _angular_core.InputSignal<MatMultiCheckboxProps | undefined>;
198
207
  readonly meta: _angular_core.InputSignal<FieldMeta | undefined>;
199
- valueViewModel: _angular_core.WritableSignal<FieldOption<T>[]>;
208
+ valueViewModel: _angular_core.WritableSignal<FieldOption<ValueType>[]>;
209
+ /** Computed map of checked option values for O(1) lookup in template */
210
+ readonly checkedValuesMap: _angular_core.Signal<Record<string, boolean>>;
200
211
  constructor();
201
- onCheckboxChange(option: FieldOption<T>, checked: boolean): void;
212
+ onCheckboxChange(option: FieldOption<ValueType>, checked: boolean): void;
202
213
  readonly validationMessages: _angular_core.InputSignal<ValidationMessages | undefined>;
203
214
  readonly defaultValidationMessages: _angular_core.InputSignal<ValidationMessages | undefined>;
204
215
  readonly resolvedErrors: _angular_core.Signal<_ng_forge_dynamic_forms_integration.ResolvedError[]>;
@@ -214,8 +225,8 @@ declare class MatMultiCheckboxFieldComponent<T extends ValueType> implements Mat
214
225
  protected readonly ariaRequired: _angular_core.Signal<true | null>;
215
226
  /** aria-describedby: links to hint and error messages for screen readers */
216
227
  protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
217
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatMultiCheckboxFieldComponent<any>, never>;
218
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatMultiCheckboxFieldComponent<any>, "df-mat-multi-checkbox", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
228
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatMultiCheckboxFieldComponent, never>;
229
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatMultiCheckboxFieldComponent, "df-mat-multi-checkbox", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
219
230
  }
220
231
 
221
232
  interface MatRadioProps {
@@ -225,17 +236,17 @@ interface MatRadioProps {
225
236
  hint?: DynamicText;
226
237
  }
227
238
  type MatRadioField<T> = RadioField<T, MatRadioProps>;
228
- type MatRadioComponent<T> = ValueFieldComponent<MatRadioField<T>>;
239
+ type MatRadioComponent = ValueFieldComponent<MatRadioField<ValueType>>;
229
240
 
230
- declare class MatRadioFieldComponent<T> implements MatRadioComponent<T> {
241
+ declare class MatRadioFieldComponent implements MatRadioComponent {
231
242
  private readonly elementRef;
232
- readonly field: _angular_core.InputSignal<FieldTree<T>>;
243
+ readonly field: _angular_core.InputSignal<FieldTree<ValueType>>;
233
244
  readonly key: _angular_core.InputSignal<string>;
234
245
  readonly label: _angular_core.InputSignal<DynamicText | undefined>;
235
246
  readonly placeholder: _angular_core.InputSignal<DynamicText | undefined>;
236
247
  readonly className: _angular_core.InputSignal<string>;
237
248
  readonly tabIndex: _angular_core.InputSignal<number | undefined>;
238
- readonly options: _angular_core.InputSignal<FieldOption<T>[]>;
249
+ readonly options: _angular_core.InputSignal<FieldOption<ValueType>[]>;
239
250
  readonly props: _angular_core.InputSignal<MatRadioProps | undefined>;
240
251
  readonly meta: _angular_core.InputSignal<FieldMeta | undefined>;
241
252
  readonly validationMessages: _angular_core.InputSignal<ValidationMessages | undefined>;
@@ -254,32 +265,32 @@ declare class MatRadioFieldComponent<T> implements MatRadioComponent<T> {
254
265
  protected readonly ariaRequired: _angular_core.Signal<true | null>;
255
266
  /** aria-describedby: links to hint and error messages for screen readers */
256
267
  protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
257
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatRadioFieldComponent<any>, never>;
258
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatRadioFieldComponent<any>, "df-mat-radio", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
268
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatRadioFieldComponent, never>;
269
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatRadioFieldComponent, "df-mat-radio", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
259
270
  }
260
271
 
261
- interface MatSelectProps<T> extends SelectProps {
272
+ interface MatSelectProps extends SelectProps {
262
273
  appearance?: MatFormFieldAppearance;
263
274
  multiple?: boolean;
264
275
  panelMaxHeight?: string;
265
276
  subscriptSizing?: SubscriptSizing;
266
- compareWith?: (o1: T, o2: T) => boolean;
277
+ compareWith?: (o1: ValueType, o2: ValueType) => boolean;
267
278
  hint?: DynamicText;
268
279
  }
269
- type MatSelectField<T> = SelectField<T, MatSelectProps<T>>;
270
- type MatSelectComponent<T> = ValueFieldComponent<MatSelectField<T>>;
280
+ type MatSelectField<T> = SelectField<T, MatSelectProps>;
281
+ type MatSelectComponent = ValueFieldComponent<MatSelectField<ValueType>>;
271
282
 
272
- declare class MatSelectFieldComponent<T> implements MatSelectComponent<T> {
283
+ declare class MatSelectFieldComponent implements MatSelectComponent {
273
284
  private materialConfig;
274
285
  private readonly elementRef;
275
- readonly field: _angular_core.InputSignal<FieldTree<T>>;
286
+ readonly field: _angular_core.InputSignal<FieldTree<ValueType>>;
276
287
  readonly key: _angular_core.InputSignal<string>;
277
288
  readonly label: _angular_core.InputSignal<DynamicText | undefined>;
278
289
  readonly placeholder: _angular_core.InputSignal<DynamicText | undefined>;
279
290
  readonly className: _angular_core.InputSignal<string>;
280
291
  readonly tabIndex: _angular_core.InputSignal<number | undefined>;
281
- readonly options: _angular_core.InputSignal<FieldOption<T>[]>;
282
- readonly props: _angular_core.InputSignal<MatSelectProps<T> | undefined>;
292
+ readonly options: _angular_core.InputSignal<FieldOption<ValueType>[]>;
293
+ readonly props: _angular_core.InputSignal<MatSelectProps | undefined>;
283
294
  readonly meta: _angular_core.InputSignal<FieldMeta | undefined>;
284
295
  readonly validationMessages: _angular_core.InputSignal<ValidationMessages | undefined>;
285
296
  readonly defaultValidationMessages: _angular_core.InputSignal<ValidationMessages | undefined>;
@@ -300,8 +311,8 @@ declare class MatSelectFieldComponent<T> implements MatSelectComponent<T> {
300
311
  protected readonly ariaRequired: _angular_core.Signal<true | null>;
301
312
  /** aria-describedby: links to hint and error messages for screen readers */
302
313
  protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
303
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatSelectFieldComponent<any>, never>;
304
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatSelectFieldComponent<any>, "df-mat-select", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
314
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatSelectFieldComponent, never>;
315
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatSelectFieldComponent, "df-mat-select", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
305
316
  }
306
317
 
307
318
  interface MatSliderProps {
@@ -489,6 +500,8 @@ declare class MatTextareaFieldComponent implements MatTextareaComponent {
489
500
  * Note: We cannot use [readonly] or [attr.readonly] bindings because Angular throws
490
501
  * NG8022: "Binding to '[readonly]' is not allowed on nodes using the '[field]' directive"
491
502
  *
503
+ * Uses afterRenderEffect to ensure DOM is ready before manipulating attributes.
504
+ *
492
505
  * @see https://github.com/angular/angular/issues/65897
493
506
  */
494
507
  private readonly syncReadonlyToDom;
@@ -549,7 +562,21 @@ declare class MatToggleFieldComponent implements MatToggleComponent {
549
562
  /** aria-required: true if field is required, null otherwise (to remove attribute) */
550
563
  protected readonly ariaRequired: _angular_core.Signal<true | null>;
551
564
  /** aria-describedby: links to hint and error messages for screen readers */
552
- protected readonly ariaDescribedBy: _angular_core.Signal<string>;
565
+ protected readonly ariaDescribedBy: _angular_core.Signal<string | null>;
566
+ /**
567
+ * Workaround: Angular Material's MatSlideToggle does NOT propagate aria-required to its internal
568
+ * button element. This effect imperatively sets/removes aria-required on the internal button.
569
+ *
570
+ * Uses afterRenderEffect to ensure DOM is ready before querying internal elements.
571
+ */
572
+ private readonly syncAriaRequiredToDom;
573
+ /**
574
+ * Workaround: Angular Material's MatSlideToggle does NOT propagate aria-describedby to its internal
575
+ * button element. This effect imperatively sets/removes aria-describedby on the internal button.
576
+ *
577
+ * Uses afterRenderEffect to ensure DOM is ready before querying internal elements.
578
+ */
579
+ private readonly syncAriaDescribedByToDom;
553
580
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatToggleFieldComponent, never>;
554
581
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MatToggleFieldComponent, "df-mat-toggle", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
555
582
  }
@@ -562,8 +589,24 @@ declare const MATERIAL_FIELD_TYPES: FieldTypeDefinition[];
562
589
 
563
590
  /**
564
591
  * Configuration options for Material Design form fields.
565
- * These settings will be applied as defaults to all Material form fields
566
- * unless overridden by individual field props.
592
+ *
593
+ * These settings can be applied at two levels:
594
+ * - **Library-level**: Via `withMaterialFields({ ... })` - applies to all forms
595
+ * - **Form-level**: Via `defaultProps` in form config - applies to a specific form
596
+ *
597
+ * The cascade hierarchy is: Library-level → Form-level → Field-level
598
+ *
599
+ * @example
600
+ * ```typescript
601
+ * // Library-level (in app config)
602
+ * provideDynamicForms(withMaterialFields({ appearance: 'outline' }))
603
+ *
604
+ * // Form-level (in form config)
605
+ * const config: MatFormConfig = {
606
+ * defaultProps: { appearance: 'fill' },
607
+ * fields: [...]
608
+ * };
609
+ * ```
567
610
  */
568
611
  interface MaterialConfig {
569
612
  /**
@@ -581,6 +624,16 @@ interface MaterialConfig {
581
624
  * @default false
582
625
  */
583
626
  disableRipple?: boolean;
627
+ /**
628
+ * Default color theme for form controls (checkboxes, radios, sliders, toggles)
629
+ * @default 'primary'
630
+ */
631
+ color?: ThemePalette;
632
+ /**
633
+ * Default label position for checkboxes and radios
634
+ * @default 'after'
635
+ */
636
+ labelPosition?: 'before' | 'after';
584
637
  }
585
638
 
586
639
  /**
@@ -629,6 +682,51 @@ declare const MatField: {
629
682
  };
630
683
  type MatFieldType = (typeof MatField)[keyof typeof MatField];
631
684
 
685
+ /**
686
+ * Material-specific props that can be set at form level and cascade to all fields.
687
+ *
688
+ * This is the same type as `MaterialConfig` used in `withMaterialFields()`.
689
+ * Using a single type ensures consistency between library-level and form-level configuration.
690
+ *
691
+ * The cascade hierarchy is: Library-level → Form-level → Field-level
692
+ *
693
+ * @example
694
+ * ```typescript
695
+ * const config: MatFormConfig = {
696
+ * defaultProps: {
697
+ * appearance: 'outline',
698
+ * subscriptSizing: 'dynamic',
699
+ * color: 'accent',
700
+ * },
701
+ * fields: [
702
+ * { type: 'mat-input', key: 'name', label: 'Name' },
703
+ * ],
704
+ * };
705
+ * ```
706
+ */
707
+ type MatFormProps = MaterialConfig;
708
+ /**
709
+ * Material-specific FormConfig with type-safe defaultProps.
710
+ *
711
+ * Use this type alias when defining form configurations with Material Design components
712
+ * to get IDE autocomplete and type checking for `defaultProps`.
713
+ *
714
+ * @example
715
+ * ```typescript
716
+ * const formConfig: MatFormConfig = {
717
+ * defaultProps: {
718
+ * appearance: 'outline',
719
+ * subscriptSizing: 'dynamic',
720
+ * },
721
+ * fields: [
722
+ * { type: 'mat-input', key: 'name', label: 'Name' }, // Uses form defaultProps
723
+ * { type: 'mat-input', key: 'email', props: { appearance: 'fill' } }, // Override
724
+ * ],
725
+ * };
726
+ * ```
727
+ */
728
+ type MatFormConfig<TFields extends NarrowFields | RegisteredFieldTypes[] = RegisteredFieldTypes[], TValue = InferFormValue<TFields extends readonly RegisteredFieldTypes[] ? TFields : RegisteredFieldTypes[]>> = FormConfig<TFields, TValue, MatFormProps>;
729
+
632
730
  /**
633
731
  * Module augmentation for @ng-forge/dynamic-form
634
732
  * This file augments the FieldRegistryLeaves interface to include
@@ -722,4 +820,4 @@ declare module '@ng-forge/dynamic-forms' {
722
820
  }
723
821
 
724
822
  export { MATERIAL_CONFIG, MATERIAL_FIELD_TYPES, MatButtonFieldComponent, MatCheckboxFieldComponent, MatDatepickerFieldComponent, MatField, MatInputFieldComponent, MatMultiCheckboxFieldComponent, MatRadioFieldComponent, MatSelectFieldComponent, MatSliderFieldComponent, MatTextareaFieldComponent, MatToggleFieldComponent, withMaterialFields };
725
- export type { AddArrayItemButtonField, MatButtonField, MatButtonProps, MatCheckboxComponent, MatCheckboxField, MatCheckboxProps, MatDatepickerComponent, MatDatepickerField, MatDatepickerProps, MatFieldType, 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, RemoveArrayItemButtonField };
823
+ export type { AddArrayItemButtonField, 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, RemoveArrayItemButtonField };