@ng-forge/dynamic-forms 0.5.2 → 0.6.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.
@@ -251,6 +251,30 @@ interface FieldDef<TProps, TMeta extends FieldMeta = FieldMeta> {
251
251
  * ```
252
252
  */
253
253
  tabIndex?: number | undefined;
254
+ /**
255
+ * Whether to exclude this field's value from submission output when hidden.
256
+ *
257
+ * Overrides both the global `withValueExclusionDefaults()` and form-level `FormOptions` settings.
258
+ *
259
+ * @default undefined (uses form-level or global setting)
260
+ */
261
+ excludeValueIfHidden?: boolean;
262
+ /**
263
+ * Whether to exclude this field's value from submission output when disabled.
264
+ *
265
+ * Overrides both the global `withValueExclusionDefaults()` and form-level `FormOptions` settings.
266
+ *
267
+ * @default undefined (uses form-level or global setting)
268
+ */
269
+ excludeValueIfDisabled?: boolean;
270
+ /**
271
+ * Whether to exclude this field's value from submission output when readonly.
272
+ *
273
+ * Overrides both the global `withValueExclusionDefaults()` and form-level `FormOptions` settings.
274
+ *
275
+ * @default undefined (uses form-level or global setting)
276
+ */
277
+ excludeValueIfReadonly?: boolean;
254
278
  /**
255
279
  * Column sizing configuration for responsive grid layout.
256
280
  *
@@ -447,6 +471,249 @@ interface ResolvedField {
447
471
  inputs: Signal<Record<string, unknown>>;
448
472
  }
449
473
 
474
+ /**
475
+ * Configuration for an HTTP request used by declarative HTTP validators, derivations, and conditions.
476
+ *
477
+ * All string values in `queryParams` are treated as expressions evaluated by ExpressionParser.
478
+ * When `evaluateBodyExpressions` is true, top-level string values in `body` are also evaluated as expressions (shallow only).
479
+ */
480
+ interface HttpRequestConfig {
481
+ /** URL to send the request to */
482
+ url: string;
483
+ /** HTTP method. Defaults to 'GET' */
484
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
485
+ /**
486
+ * URL path parameters. Keys correspond to `:key` placeholders in the URL.
487
+ * Values are expressions evaluated by ExpressionParser against the current EvaluationContext.
488
+ *
489
+ * @example
490
+ * ```typescript
491
+ * {
492
+ * url: '/api/users/:userId/orders/:orderId',
493
+ * params: { userId: 'formValue.userId', orderId: 'fieldValue' }
494
+ * }
495
+ * // With userId=42 and fieldValue='abc' → '/api/users/42/orders/abc'
496
+ * ```
497
+ */
498
+ params?: Record<string, string>;
499
+ /**
500
+ * Query parameters appended to the URL.
501
+ * Values are expressions evaluated by ExpressionParser against the current EvaluationContext.
502
+ */
503
+ queryParams?: Record<string, string>;
504
+ /** Request body (for POST/PUT/PATCH) */
505
+ body?: Record<string, unknown>;
506
+ /**
507
+ * When true, top-level string values in `body` are treated as expressions
508
+ * and evaluated by ExpressionParser (shallow only — nested objects are passed through as-is).
509
+ */
510
+ evaluateBodyExpressions?: boolean;
511
+ /** HTTP headers to include in the request */
512
+ headers?: Record<string, string>;
513
+ }
514
+
515
+ /**
516
+ * Comparison operators for field value and form value conditions.
517
+ *
518
+ * @public
519
+ */
520
+ type ComparisonOperator = 'equals' | 'notEquals' | 'greater' | 'less' | 'greaterOrEqual' | 'lessOrEqual' | 'contains' | 'startsWith' | 'endsWith' | 'matches';
521
+ /**
522
+ * Condition that compares a specific field's value against an expected value.
523
+ *
524
+ * @public
525
+ */
526
+ interface FieldValueCondition {
527
+ type: 'fieldValue';
528
+ /** Path to the field whose value to compare */
529
+ fieldPath: string;
530
+ /** Comparison operator */
531
+ operator: ComparisonOperator;
532
+ /** Value to compare against */
533
+ value?: unknown;
534
+ }
535
+ /**
536
+ * Condition that compares the entire form value against an expected value.
537
+ *
538
+ * @deprecated Use `FieldValueCondition` for specific field checks, or
539
+ * `JavascriptCondition` with an expression for complex form-level comparisons.
540
+ * Will be removed in a future minor version.
541
+ *
542
+ * @public
543
+ */
544
+ interface FormValueCondition {
545
+ type: 'formValue';
546
+ /** Comparison operator */
547
+ operator: ComparisonOperator;
548
+ /** Value to compare against */
549
+ value?: unknown;
550
+ }
551
+ /**
552
+ * Condition that invokes a registered custom function by name (new API).
553
+ *
554
+ * Register functions via `customFnConfig.customFunctions`.
555
+ *
556
+ * @internal
557
+ */
558
+ interface CustomConditionNew {
559
+ type: 'custom';
560
+ /** Name of the registered custom function to invoke */
561
+ functionName: string;
562
+ }
563
+ /**
564
+ * @deprecated Use `CustomCondition` with `functionName` instead.
565
+ * The `expression` field was misnamed — it holds a function registry key, not a JS expression.
566
+ * Will be removed in a future minor version.
567
+ *
568
+ * @internal
569
+ */
570
+ interface CustomConditionDeprecated {
571
+ type: 'custom';
572
+ /**
573
+ * @deprecated Use `functionName` instead. Will be removed in a future minor version.
574
+ */
575
+ expression: string;
576
+ }
577
+ /**
578
+ * Condition that invokes a registered custom function by name.
579
+ *
580
+ * Use `functionName` (new API). The `expression` field is deprecated.
581
+ * Register functions via `customFnConfig.customFunctions`.
582
+ *
583
+ * @public
584
+ */
585
+ type CustomCondition = CustomConditionNew | CustomConditionDeprecated;
586
+ /**
587
+ * Condition that evaluates a JavaScript expression using the secure AST-based parser.
588
+ *
589
+ * The expression has access to `formValue`, `fieldValue`, `externalData`, etc.
590
+ *
591
+ * @public
592
+ */
593
+ interface JavascriptCondition {
594
+ type: 'javascript';
595
+ /** JavaScript expression string to evaluate */
596
+ expression: string;
597
+ }
598
+ /**
599
+ * Condition that evaluates based on an HTTP response from a remote server.
600
+ *
601
+ * The HTTP request is resolved reactively — when dependent form values change,
602
+ * the request is re-evaluated (with debouncing). The result is cached per
603
+ * resolved request to avoid redundant network calls.
604
+ *
605
+ * Since `LogicFn` must return `boolean` synchronously, this condition uses
606
+ * a signal-based async resolution pattern internally.
607
+ *
608
+ * @public
609
+ */
610
+ interface HttpCondition {
611
+ type: 'http';
612
+ /** HTTP request configuration */
613
+ http: HttpRequestConfig;
614
+ /**
615
+ * Expression to extract boolean from response (scope: `{ response }`).
616
+ * e.g. `'response.allowed'`, `'response.permissions.canEdit'`
617
+ * When omitted, the entire response is coerced to boolean: `!!response`
618
+ */
619
+ responseExpression?: string;
620
+ /**
621
+ * Value to return while the HTTP request is in-flight.
622
+ *
623
+ * Choose based on the logic type and desired UX:
624
+ * - For `hidden`: `false` = visible while loading, `true` = hidden while loading
625
+ * - For `disabled`: `false` = enabled while loading, `true` = disabled while loading
626
+ * - For `required`: `false` = optional while loading, `true` = required while loading
627
+ *
628
+ * @default false
629
+ */
630
+ pendingValue?: boolean;
631
+ /** Cache duration in ms for HTTP responses. @default 30000 */
632
+ cacheDurationMs?: number;
633
+ /**
634
+ * Debounce time in milliseconds for re-evaluation when dependent form values change.
635
+ * @default 300
636
+ */
637
+ debounceMs?: number;
638
+ }
639
+ /**
640
+ * Condition that evaluates based on a registered async function.
641
+ *
642
+ * The function is resolved reactively — when dependent form values change,
643
+ * the function is re-evaluated (with debouncing). The result is cached per
644
+ * evaluation to avoid redundant calls.
645
+ *
646
+ * Since `LogicFn` must return `boolean` synchronously, this condition uses
647
+ * a signal-based async resolution pattern internally.
648
+ *
649
+ * @public
650
+ */
651
+ interface AsyncCondition {
652
+ type: 'async';
653
+ /** Name of the registered async condition function */
654
+ asyncFunctionName: string;
655
+ /**
656
+ * Value to return while async resolution is pending.
657
+ *
658
+ * Choose based on the logic type and desired UX:
659
+ * - For `hidden`: `false` = visible while loading, `true` = hidden while loading
660
+ * - For `disabled`: `false` = enabled while loading, `true` = disabled while loading
661
+ * - For `required`: `false` = optional while loading, `true` = required while loading
662
+ *
663
+ * @default false
664
+ */
665
+ pendingValue?: boolean;
666
+ /**
667
+ * Debounce ms for re-evaluation.
668
+ * @default 300
669
+ */
670
+ debounceMs?: number;
671
+ }
672
+ /**
673
+ * Logical AND — all sub-conditions must be true.
674
+ *
675
+ * @public
676
+ */
677
+ interface AndCondition {
678
+ type: 'and';
679
+ /** Sub-conditions that must all evaluate to true */
680
+ conditions: ConditionalExpression[];
681
+ }
682
+ /**
683
+ * Logical OR — at least one sub-condition must be true.
684
+ *
685
+ * @public
686
+ */
687
+ interface OrCondition {
688
+ type: 'or';
689
+ /** Sub-conditions where at least one must evaluate to true */
690
+ conditions: ConditionalExpression[];
691
+ }
692
+ /**
693
+ * Discriminated union of all conditional expression types.
694
+ *
695
+ * Each variant only allows the properties relevant to its type,
696
+ * providing compile-time safety against invalid property combinations.
697
+ *
698
+ * @public
699
+ */
700
+ type ConditionalExpression = FieldValueCondition | FormValueCondition | CustomCondition | JavascriptCondition | HttpCondition | AsyncCondition | AndCondition | OrCondition;
701
+
702
+ /**
703
+ * Logic configuration for container fields (page, group, row, array).
704
+ * Containers only support the 'hidden' logic type since they are layout containers,
705
+ * not form controls (they can't be readonly, disabled, or required).
706
+ */
707
+ interface ContainerLogicConfig {
708
+ /** Only 'hidden' is supported for container fields */
709
+ type: 'hidden';
710
+ /**
711
+ * Condition that determines when this container is hidden.
712
+ * Can be a boolean or a conditional expression evaluated against form values.
713
+ */
714
+ condition: ConditionalExpression | boolean;
715
+ }
716
+
450
717
  /**
451
718
  * Row field interface for creating horizontal layouts
452
719
  * This is a special field type that contains other definitions arranged horizontally
@@ -467,6 +734,11 @@ interface RowField<TFields extends readonly RowAllowedChildren[] = readonly RowA
467
734
  readonly label?: never;
468
735
  /** Rows do not support meta - they have no native form element **/
469
736
  readonly meta?: never;
737
+ /**
738
+ * Logic configurations for conditional row visibility.
739
+ * Only 'hidden' type logic is supported for rows.
740
+ */
741
+ readonly logic?: ContainerLogicConfig[];
470
742
  }
471
743
  /**
472
744
  * Type guard for RowField with proper type narrowing
@@ -491,6 +763,11 @@ interface GroupField<TFields extends readonly GroupAllowedChildren[] = readonly
491
763
  readonly label?: never;
492
764
  /** Groups do not support meta - they have no native form element **/
493
765
  readonly meta?: never;
766
+ /**
767
+ * Logic configurations for conditional group visibility.
768
+ * Only 'hidden' type logic is supported for groups.
769
+ */
770
+ readonly logic?: ContainerLogicConfig[];
494
771
  }
495
772
  /**
496
773
  * Type guard for GroupField with proper type narrowing
@@ -559,13 +836,13 @@ interface HiddenField<TValue extends HiddenValue = HiddenValue> extends FieldDef
559
836
  * Fields that are allowed as children of Page fields
560
837
  * Pages can contain: rows, groups, arrays, and leaf fields (but NOT other pages)
561
838
  */
562
- type PageAllowedChildren = LeafFieldTypes | RowField | GroupField | ArrayField;
839
+ type PageAllowedChildren = LeafFieldTypes | RowField | GroupField | ArrayField | SimplifiedArrayField;
563
840
  /**
564
841
  * Fields that are allowed as children of Row fields
565
842
  * Rows can contain: groups, arrays, and leaf fields (but NOT pages, other rows, or hidden fields)
566
843
  * Hidden fields are excluded because rows are for horizontal layouts and hidden fields don't render
567
844
  */
568
- type RowAllowedChildren = Exclude<LeafFieldTypes, HiddenField> | GroupField | ArrayField;
845
+ type RowAllowedChildren = Exclude<LeafFieldTypes, HiddenField> | GroupField | ArrayField | SimplifiedArrayField;
569
846
  /**
570
847
  * Fields that are allowed as children of Group fields
571
848
  * Groups can contain: rows and leaf fields (but NOT pages or other groups)
@@ -582,7 +859,7 @@ type ArrayAllowedChildren = LeafFieldTypes | RowField | GroupField;
582
859
  * An array item template is an array of allowed children that defines one OBJECT array item's fields.
583
860
  * Used for object arrays where each item is `{ key1: value1, key2: value2, ... }`.
584
861
  */
585
- type ArrayItemTemplate$1 = readonly ArrayAllowedChildren[];
862
+ type ArrayItemTemplate = readonly ArrayAllowedChildren[];
586
863
  /**
587
864
  * An array item definition can be either:
588
865
  * - A single field (ArrayAllowedChildren) for PRIMITIVE array items - extracts field value directly
@@ -593,7 +870,7 @@ type ArrayItemTemplate$1 = readonly ArrayAllowedChildren[];
593
870
  * - Object arrays: `[{ name: 'Alice', email: '...' }]`
594
871
  * - Heterogeneous arrays: `[{ value: 'x' }, 'y']` (mixed primitives and objects)
595
872
  */
596
- type ArrayItemDefinition = ArrayAllowedChildren | ArrayItemTemplate$1;
873
+ type ArrayItemDefinition = ArrayAllowedChildren | ArrayItemTemplate;
597
874
  /**
598
875
  * Array field interface for creating dynamic field collections that map to array values.
599
876
  *
@@ -669,6 +946,21 @@ interface ArrayField<TFields extends readonly ArrayItemDefinition[] = readonly A
669
946
  readonly label?: never;
670
947
  /** Arrays do not support meta - they have no native form element **/
671
948
  readonly meta?: never;
949
+ /**
950
+ * Logic configurations for conditional array visibility.
951
+ * Only 'hidden' type logic is supported for arrays.
952
+ */
953
+ readonly logic?: ContainerLogicConfig[];
954
+ /**
955
+ * Minimum number of items required in the array.
956
+ * Validation fails if the array has fewer items than this value.
957
+ */
958
+ readonly minLength?: number;
959
+ /**
960
+ * Maximum number of items allowed in the array.
961
+ * Validation fails if the array has more items than this value.
962
+ */
963
+ readonly maxLength?: number;
672
964
  }
673
965
  /**
674
966
  * Type guard for ArrayField with proper type narrowing.
@@ -676,36 +968,103 @@ interface ArrayField<TFields extends readonly ArrayItemDefinition[] = readonly A
676
968
  * Fields can contain either single FieldDefs (primitive items) or arrays of FieldDefs (object items).
677
969
  */
678
970
  declare function isArrayField(field: FieldDef<any>): field is ArrayField;
679
-
680
- interface ConditionalExpression {
681
- /** Expression type */
682
- type: 'fieldValue' | 'formValue' | 'custom' | 'javascript' | 'and' | 'or';
683
- /** Field path for fieldValue type */
684
- fieldPath?: string;
685
- /** Comparison operator */
686
- operator?: 'equals' | 'notEquals' | 'greater' | 'less' | 'greaterOrEqual' | 'lessOrEqual' | 'contains' | 'startsWith' | 'endsWith' | 'matches';
687
- /** Value to compare against */
688
- value?: unknown;
689
- /** JavaScript expression for custom logic */
690
- expression?: string;
691
- /** Array of sub-conditions for 'and' and 'or' types */
692
- conditions?: ConditionalExpression[];
971
+ /**
972
+ * Configuration for auto-generated add/remove buttons in simplified array fields.
973
+ */
974
+ interface ArrayButtonConfig {
975
+ /** Custom label for the button */
976
+ readonly label?: string;
977
+ /** Additional properties passed to the button component */
978
+ readonly props?: Record<string, unknown>;
693
979
  }
694
-
695
980
  /**
696
- * Logic configuration for page fields.
697
- * Pages only support the 'hidden' logic type since they are layout containers,
698
- * not form controls (they can't be readonly, disabled, or required).
981
+ * Simplified array field interface for common use cases.
982
+ *
983
+ * Instead of manually specifying each item in `fields`, provide a `template` that defines
984
+ * the structure of a single item, and a `value` array with initial data.
985
+ * The library auto-generates add/remove buttons.
986
+ *
987
+ * Discriminant: `template` presence → simplified API; `Array.isArray(template)` → object vs primitive.
988
+ *
989
+ * @example
990
+ * // Primitive array: ['angular', 'typescript']
991
+ * {
992
+ * key: 'tags',
993
+ * type: 'array',
994
+ * template: { key: 'value', type: 'input', label: 'Tag', required: true },
995
+ * value: ['angular', 'typescript']
996
+ * }
997
+ *
998
+ * @example
999
+ * // Object array: [{ name: 'Jane', phone: '555' }]
1000
+ * {
1001
+ * key: 'contacts',
1002
+ * type: 'array',
1003
+ * template: [
1004
+ * { key: 'name', type: 'input', label: 'Contact Name', required: true },
1005
+ * { key: 'phone', type: 'input', label: 'Phone Number' },
1006
+ * ],
1007
+ * value: [{ name: 'Jane', phone: '555' }]
1008
+ * }
1009
+ *
1010
+ * @example
1011
+ * // Button customization / opt-out
1012
+ * {
1013
+ * key: 'tags',
1014
+ * type: 'array',
1015
+ * template: { key: 'value', type: 'input', label: 'Tag' },
1016
+ * addButton: { label: 'Add Tag', props: { color: 'primary' } },
1017
+ * removeButton: false
1018
+ * }
699
1019
  */
700
- interface PageLogicConfig {
701
- /** Only 'hidden' is supported for pages */
702
- type: 'hidden';
1020
+ interface SimplifiedArrayField extends FieldDef<never> {
1021
+ type: 'array';
703
1022
  /**
704
- * Condition that determines when this page is hidden.
705
- * Can be a boolean or a conditional expression evaluated against form values.
1023
+ * Template defining the structure of a single array item.
1024
+ * - Single field (ArrayAllowedChildren) → primitive array (each item is a single value)
1025
+ * - Array of fields (readonly ArrayAllowedChildren[]) → object array (each item is an object)
706
1026
  */
707
- condition: ConditionalExpression | boolean;
1027
+ readonly template: ArrayAllowedChildren | readonly ArrayAllowedChildren[];
1028
+ /** Initial values for the array. Each element creates one array item. */
1029
+ readonly value?: readonly unknown[];
1030
+ /**
1031
+ * Configuration for the auto-generated "Add" button, or `false` to disable it.
1032
+ * Defaults to a button with label "Add".
1033
+ */
1034
+ readonly addButton?: ArrayButtonConfig | false;
1035
+ /**
1036
+ * Configuration for the auto-generated "Remove" button on each item, or `false` to disable it.
1037
+ * Defaults to a button with label "Remove".
1038
+ */
1039
+ readonly removeButton?: ArrayButtonConfig | false;
1040
+ /** Simplified arrays do not support the label property */
1041
+ readonly label?: never;
1042
+ /** Simplified arrays do not support meta */
1043
+ readonly meta?: never;
1044
+ /**
1045
+ * Logic configurations for conditional array visibility.
1046
+ * Only 'hidden' type logic is supported for arrays.
1047
+ */
1048
+ readonly logic?: ContainerLogicConfig[];
1049
+ /**
1050
+ * Minimum number of items required in the array.
1051
+ * Validation fails if the array has fewer items than this value.
1052
+ */
1053
+ readonly minLength?: number;
1054
+ /**
1055
+ * Maximum number of items allowed in the array.
1056
+ * Validation fails if the array has more items than this value.
1057
+ */
1058
+ readonly maxLength?: number;
1059
+ /** Mutually exclusive with `template` — use `fields` for the full API instead */
1060
+ readonly fields?: never;
708
1061
  }
1062
+ /**
1063
+ * Type guard for SimplifiedArrayField.
1064
+ * Checks for `type: 'array'` with a `template` property (discriminant from full ArrayField).
1065
+ */
1066
+ declare function isSimplifiedArrayField(field: FieldDef<any>): field is SimplifiedArrayField;
1067
+
709
1068
  /**
710
1069
  * Page field interface for creating top-level page layouts
711
1070
  * This is a special field type that contains other field definitions
@@ -749,7 +1108,7 @@ interface PageField<TFields extends readonly PageAllowedChildren[] = PageAllowed
749
1108
  * }
750
1109
  * ```
751
1110
  */
752
- readonly logic?: PageLogicConfig[];
1111
+ readonly logic?: ContainerLogicConfig[];
753
1112
  }
754
1113
  /**
755
1114
  * Type guard for PageField with proper type narrowing
@@ -916,19 +1275,52 @@ interface DebouncedStateLogicConfig extends BaseStateLogicConfig {
916
1275
  */
917
1276
  type StateLogicConfig = ImmediateStateLogicConfig | DebouncedStateLogicConfig;
918
1277
  /**
919
- * Base configuration for value derivation logic.
920
- *
921
- * All derivations target the field they are defined on (self-targeting).
922
- * This simplifies configuration by removing the need for `targetField` -
923
- * derivation logic is placed on the field that should receive the computed value.
1278
+ * Shared fields that appear on all derivation logic config variants.
924
1279
  *
925
1280
  * @internal
926
1281
  */
927
- interface BaseDerivationLogicConfig {
1282
+ interface SharedDerivationFields {
928
1283
  /**
929
1284
  * Logic type identifier for value derivation.
930
1285
  */
931
1286
  type: 'derivation';
1287
+ /**
1288
+ * Target property name for property derivation.
1289
+ *
1290
+ * When set, this derivation targets a field property (like `minDate`, `options`,
1291
+ * `label`, `placeholder`) instead of the field's value. The derivation is routed
1292
+ * to the property derivation pipeline.
1293
+ *
1294
+ * When absent, the derivation targets the field's value (default behavior).
1295
+ *
1296
+ * **Depth limit (max 2 levels):** Only simple and single-dot-nested paths are
1297
+ * supported. Paths with 2+ dots (e.g., `'a.b.c'`) will throw at runtime.
1298
+ *
1299
+ * @example
1300
+ * ```typescript
1301
+ * // Property derivation (new unified API)
1302
+ * {
1303
+ * key: 'endDate',
1304
+ * type: 'datepicker',
1305
+ * logic: [{
1306
+ * type: 'derivation',
1307
+ * targetProperty: 'minDate',
1308
+ * expression: 'formValue.startDate'
1309
+ * }]
1310
+ * }
1311
+ *
1312
+ * // Value derivation (no targetProperty — existing behavior)
1313
+ * {
1314
+ * key: 'total',
1315
+ * type: 'input',
1316
+ * logic: [{
1317
+ * type: 'derivation',
1318
+ * expression: 'formValue.quantity * formValue.unitPrice'
1319
+ * }]
1320
+ * }
1321
+ * ```
1322
+ */
1323
+ targetProperty?: string;
932
1324
  /**
933
1325
  * Optional name for this derivation for debugging purposes.
934
1326
  *
@@ -976,74 +1368,199 @@ interface BaseDerivationLogicConfig {
976
1368
  */
977
1369
  condition?: ConditionalExpression | boolean;
978
1370
  /**
979
- * Static value to set on this field.
1371
+ * When true, the derivation stops running after the user manually
1372
+ * edits the target field.
980
1373
  *
981
- * Use when the derived value is a constant.
982
- * Mutually exclusive with `expression` and `functionName`.
1374
+ * This is useful for "smart defaults" — values that should be
1375
+ * auto-filled initially but respected once the user explicitly changes them.
1376
+ *
1377
+ * Uses the field's `dirty()` signal to detect user modification.
1378
+ * Derivations write directly to `value.set()` which does not trigger
1379
+ * `markAsDirty()`, so `dirty === true` reliably indicates a user edit.
983
1380
  *
984
1381
  * @example
985
1382
  * ```typescript
986
- * value: '+1' // String
987
- * value: 100 // Number
988
- * value: true // Boolean
989
- * value: { code: 'US' } // Object
1383
+ * // Auto-fill display name from first + last name, but stop if user edits it
1384
+ * {
1385
+ * key: 'displayName',
1386
+ * logic: [{
1387
+ * type: 'derivation',
1388
+ * expression: 'formValue.firstName + " " + formValue.lastName',
1389
+ * stopOnUserOverride: true
1390
+ * }]
1391
+ * }
990
1392
  * ```
991
1393
  */
992
- value?: unknown;
1394
+ stopOnUserOverride?: boolean;
993
1395
  /**
994
- * JavaScript expression to evaluate for the derived value.
1396
+ * When true (and `stopOnUserOverride` is also true), clears the
1397
+ * user-override flag when any dependency of this derivation changes,
1398
+ * allowing the derivation to run again.
995
1399
  *
996
- * Has access to `formValue` object containing all form values.
997
- * For array fields, `formValue` is scoped to the current array item.
998
- * Uses the same secure AST-based parser as other expressions.
999
- * Mutually exclusive with `value` and `functionName`.
1400
+ * This is useful when a user override should only persist until the
1401
+ * underlying data changes — e.g., when switching countries, the
1402
+ * phone prefix should re-derive even if the user previously edited it.
1000
1403
  *
1001
1404
  * @example
1002
1405
  * ```typescript
1003
- * expression: 'formValue.quantity * formValue.unitPrice'
1004
- * expression: 'formValue.firstName + " " + formValue.lastName'
1005
- * expression: 'formValue.price * (1 - formValue.discount / 100)'
1406
+ * {
1407
+ * key: 'phonePrefix',
1408
+ * logic: [{
1409
+ * type: 'derivation',
1410
+ * value: '+1',
1411
+ * condition: { type: 'fieldValue', fieldPath: 'country', operator: 'equals', value: 'USA' },
1412
+ * stopOnUserOverride: true,
1413
+ * reEngageOnDependencyChange: true,
1414
+ * dependsOn: ['country']
1415
+ * }]
1416
+ * }
1006
1417
  * ```
1007
1418
  */
1008
- expression?: string;
1419
+ reEngageOnDependencyChange?: boolean;
1420
+ }
1421
+ /**
1422
+ * Trigger variants for derivation timing.
1423
+ * @internal
1424
+ */
1425
+ type ImmediateDerivationTrigger = {
1426
+ trigger?: 'onChange';
1427
+ debounceMs?: never;
1428
+ };
1429
+ type DebouncedDerivationTrigger = {
1430
+ trigger: 'debounced';
1431
+ debounceMs?: number;
1432
+ };
1433
+ /**
1434
+ * Base for HTTP derivations. `source: 'http'` is required.
1435
+ * TypeScript enforces `dependsOn` and `responseExpression` at the type level.
1436
+ *
1437
+ * @internal
1438
+ */
1439
+ interface HttpDerivationBase extends SharedDerivationFields {
1440
+ /** Identifies this derivation as HTTP-driven. */
1441
+ source: 'http';
1009
1442
  /**
1010
- * Name of a registered custom derivation function.
1443
+ * HTTP request configuration for server-driven derivations.
1011
1444
  *
1012
- * The function receives the evaluation context and returns the derived value.
1013
- * Register functions in `customFnConfig.derivations`.
1014
- * Mutually exclusive with `value` and `expression`.
1445
+ * The request is sent when dependencies change, with automatic
1446
+ * debouncing and cancellation of in-flight requests.
1447
+ *
1448
+ * Configure debounce via the `trigger: 'debounced'` + `debounceMs` mechanism.
1015
1449
  *
1016
1450
  * @example
1017
1451
  * ```typescript
1018
- * functionName: 'getCurrencyForCountry'
1019
- * functionName: 'calculateTax'
1020
- * functionName: 'formatPhoneNumber'
1452
+ * {
1453
+ * key: 'exchangeRate',
1454
+ * logic: [{
1455
+ * type: 'derivation',
1456
+ * source: 'http',
1457
+ * http: {
1458
+ * url: '/api/exchange-rate',
1459
+ * method: 'GET',
1460
+ * queryParams: {
1461
+ * from: 'formValue.sourceCurrency',
1462
+ * to: 'formValue.targetCurrency',
1463
+ * },
1464
+ * },
1465
+ * responseExpression: 'response.rate',
1466
+ * dependsOn: ['sourceCurrency', 'targetCurrency'],
1467
+ * }]
1468
+ * }
1021
1469
  * ```
1022
1470
  */
1023
- functionName?: string;
1471
+ http: HttpRequestConfig;
1472
+ /**
1473
+ * Explicit field dependencies. Required for HTTP derivations to prevent
1474
+ * wildcard triggering on every keystroke.
1475
+ */
1476
+ dependsOn: string[];
1024
1477
  /**
1025
- * Explicit field dependencies for derivations.
1478
+ * Expression to extract the derived value from the HTTP response.
1026
1479
  *
1027
- * When using `functionName`, you can optionally specify which fields
1028
- * the function depends on. This enables more efficient re-evaluation
1029
- * by only triggering when specific dependencies change.
1480
+ * Evaluated via `ExpressionParser` with `{ response }` as the evaluation scope.
1030
1481
  *
1031
- * If not provided with `functionName`, defaults to all fields ('*').
1032
- * For `expression`, dependencies are automatically extracted from the expression.
1033
- * For `value`, no dependencies are needed (static value).
1482
+ * @example
1483
+ * ```typescript
1484
+ * responseExpression: 'response.rate'
1485
+ * responseExpression: 'response.data.suggestedPrice'
1486
+ * ```
1487
+ */
1488
+ responseExpression: string;
1489
+ value?: never;
1490
+ expression?: never;
1491
+ functionName?: never;
1492
+ asyncFunctionName?: never;
1493
+ }
1494
+ /**
1495
+ * Base for async function derivations. `source: 'asyncFunction'` is required.
1496
+ * TypeScript enforces `dependsOn` at the type level.
1497
+ *
1498
+ * @internal
1499
+ */
1500
+ interface AsyncFunctionDerivationBase extends SharedDerivationFields {
1501
+ /** Identifies this derivation as async-function-driven. */
1502
+ source: 'asyncFunction';
1503
+ /**
1504
+ * Name of a registered async derivation function.
1505
+ *
1506
+ * The function receives the evaluation context and returns a Promise or Observable
1507
+ * of the derived value. Register functions in `customFnConfig.asyncDerivations`.
1034
1508
  *
1035
1509
  * @example
1036
1510
  * ```typescript
1037
- * // Only re-evaluate when country changes
1038
1511
  * {
1039
- * key: 'currency',
1512
+ * key: 'suggestedPrice',
1040
1513
  * logic: [{
1041
1514
  * type: 'derivation',
1042
- * functionName: 'getCurrencyForCountry',
1043
- * dependsOn: ['country']
1515
+ * source: 'asyncFunction',
1516
+ * asyncFunctionName: 'fetchSuggestedPrice',
1517
+ * dependsOn: ['productId', 'quantity'],
1044
1518
  * }]
1045
1519
  * }
1520
+ * ```
1521
+ */
1522
+ asyncFunctionName: string;
1523
+ /**
1524
+ * Explicit field dependencies. Required for async derivations to prevent
1525
+ * wildcard triggering on every form change.
1526
+ */
1527
+ dependsOn: string[];
1528
+ value?: never;
1529
+ expression?: never;
1530
+ functionName?: never;
1531
+ http?: never;
1532
+ responseExpression?: never;
1533
+ }
1534
+ /**
1535
+ * Base for expression derivations.
1536
+ *
1537
+ * @internal
1538
+ */
1539
+ interface ExpressionDerivationBase extends SharedDerivationFields {
1540
+ source?: never;
1541
+ /**
1542
+ * JavaScript expression to evaluate for the derived value.
1046
1543
  *
1544
+ * Has access to `formValue` object containing all form values.
1545
+ * For array fields, `formValue` is scoped to the current array item.
1546
+ * Uses the same secure AST-based parser as other expressions.
1547
+ *
1548
+ * @example
1549
+ * ```typescript
1550
+ * expression: 'formValue.quantity * formValue.unitPrice'
1551
+ * expression: 'formValue.firstName + " " + formValue.lastName'
1552
+ * expression: 'formValue.price * (1 - formValue.discount / 100)'
1553
+ * ```
1554
+ */
1555
+ expression: string;
1556
+ /**
1557
+ * Explicit field dependencies for expressions.
1558
+ *
1559
+ * For `expression`, dependencies are automatically extracted from the expression.
1560
+ * Provide `dependsOn` to override automatic detection for complex expressions.
1561
+ *
1562
+ * @example
1563
+ * ```typescript
1047
1564
  * // Override automatic detection for complex expressions
1048
1565
  * {
1049
1566
  * key: 'total',
@@ -1056,41 +1573,144 @@ interface BaseDerivationLogicConfig {
1056
1573
  * ```
1057
1574
  */
1058
1575
  dependsOn?: string[];
1576
+ value?: never;
1577
+ functionName?: never;
1578
+ http?: never;
1579
+ asyncFunctionName?: never;
1580
+ responseExpression?: never;
1059
1581
  }
1060
1582
  /**
1061
- * Derivation logic that evaluates immediately on change (default).
1583
+ * Base for value derivations.
1062
1584
  *
1063
1585
  * @internal
1064
1586
  */
1065
- interface OnChangeDerivationLogicConfig extends BaseDerivationLogicConfig {
1587
+ interface ValueDerivationBase extends SharedDerivationFields {
1588
+ source?: never;
1066
1589
  /**
1067
- * Trigger for immediate evaluation.
1068
- * @default 'onChange'
1590
+ * Static value to set on this field.
1591
+ *
1592
+ * Use when the derived value is a constant.
1593
+ *
1594
+ * @example
1595
+ * ```typescript
1596
+ * value: '+1' // String
1597
+ * value: 100 // Number
1598
+ * value: true // Boolean
1599
+ * value: { code: 'US' } // Object
1600
+ * ```
1069
1601
  */
1070
- trigger?: 'onChange';
1071
- /** Not allowed for onChange trigger */
1072
- debounceMs?: never;
1602
+ value: unknown;
1603
+ /**
1604
+ * Explicit field dependencies for value derivations.
1605
+ *
1606
+ * For `value` (static), no dependencies are needed.
1607
+ * Provide `dependsOn` to conditionally re-evaluate when specific fields change.
1608
+ */
1609
+ dependsOn?: string[];
1610
+ expression?: never;
1611
+ functionName?: never;
1612
+ http?: never;
1613
+ asyncFunctionName?: never;
1614
+ responseExpression?: never;
1073
1615
  }
1074
1616
  /**
1075
- * Derivation logic that evaluates after a debounce period.
1076
- *
1077
- * Use this for self-transforms (lowercase, trim, format) to avoid
1078
- * interrupting the user while they're actively typing.
1617
+ * Base for custom sync function derivations.
1079
1618
  *
1080
1619
  * @internal
1081
1620
  */
1082
- interface DebouncedDerivationLogicConfig extends BaseDerivationLogicConfig {
1621
+ interface FunctionDerivationBase extends SharedDerivationFields {
1622
+ source?: never;
1083
1623
  /**
1084
- * Trigger for debounced evaluation.
1085
- * Evaluates after the value has stabilized for the debounce duration.
1624
+ * Name of a registered custom derivation function.
1625
+ *
1626
+ * The function receives the evaluation context and returns the derived value.
1627
+ * Register functions in `customFnConfig.derivations`.
1628
+ *
1629
+ * @example
1630
+ * ```typescript
1631
+ * functionName: 'getCurrencyForCountry'
1632
+ * functionName: 'calculateTax'
1633
+ * functionName: 'formatPhoneNumber'
1634
+ * ```
1086
1635
  */
1087
- trigger: 'debounced';
1636
+ functionName: string;
1088
1637
  /**
1089
- * Debounce duration in milliseconds.
1090
- * @default 500
1638
+ * Explicit field dependencies for function derivations.
1639
+ *
1640
+ * If not provided, defaults to all fields ('*').
1641
+ * Specify `dependsOn` for better performance when the function only
1642
+ * depends on a subset of fields.
1643
+ *
1644
+ * @example
1645
+ * ```typescript
1646
+ * // Only re-evaluate when country changes
1647
+ * {
1648
+ * key: 'currency',
1649
+ * logic: [{
1650
+ * type: 'derivation',
1651
+ * functionName: 'getCurrencyForCountry',
1652
+ * dependsOn: ['country']
1653
+ * }]
1654
+ * }
1655
+ * ```
1091
1656
  */
1092
- debounceMs?: number;
1657
+ dependsOn?: string[];
1658
+ value?: never;
1659
+ expression?: never;
1660
+ http?: never;
1661
+ asyncFunctionName?: never;
1662
+ responseExpression?: never;
1093
1663
  }
1664
+ /**
1665
+ * HTTP derivation that evaluates immediately on change (default).
1666
+ * @internal
1667
+ */
1668
+ type OnChangeHttpDerivationLogicConfig = HttpDerivationBase & ImmediateDerivationTrigger;
1669
+ /**
1670
+ * HTTP derivation that evaluates after a debounce period.
1671
+ * @internal
1672
+ */
1673
+ type DebouncedHttpDerivationLogicConfig = HttpDerivationBase & DebouncedDerivationTrigger;
1674
+ /**
1675
+ * Async function derivation that evaluates immediately on change (default).
1676
+ * @internal
1677
+ */
1678
+ type OnChangeAsyncFunctionDerivationLogicConfig = AsyncFunctionDerivationBase & ImmediateDerivationTrigger;
1679
+ /**
1680
+ * Async function derivation that evaluates after a debounce period.
1681
+ * @internal
1682
+ */
1683
+ type DebouncedAsyncFunctionDerivationLogicConfig = AsyncFunctionDerivationBase & DebouncedDerivationTrigger;
1684
+ /**
1685
+ * Expression derivation that evaluates immediately on change (default).
1686
+ * @internal
1687
+ */
1688
+ type OnChangeExpressionDerivationLogicConfig = ExpressionDerivationBase & ImmediateDerivationTrigger;
1689
+ /**
1690
+ * Expression derivation that evaluates after a debounce period.
1691
+ * @internal
1692
+ */
1693
+ type DebouncedExpressionDerivationLogicConfig = ExpressionDerivationBase & DebouncedDerivationTrigger;
1694
+ /**
1695
+ * Value derivation that evaluates immediately on change (default).
1696
+ * @internal
1697
+ */
1698
+ type OnChangeValueDerivationLogicConfig = ValueDerivationBase & ImmediateDerivationTrigger;
1699
+ /**
1700
+ * Value derivation that evaluates after a debounce period.
1701
+ * @internal
1702
+ */
1703
+ type DebouncedValueDerivationLogicConfig = ValueDerivationBase & DebouncedDerivationTrigger;
1704
+ /**
1705
+ * Function derivation that evaluates immediately on change (default).
1706
+ * @internal
1707
+ */
1708
+ type OnChangeFunctionDerivationLogicConfig = FunctionDerivationBase & ImmediateDerivationTrigger;
1709
+ /**
1710
+ * Function derivation that evaluates after a debounce period.
1711
+ * @internal
1712
+ */
1713
+ type DebouncedFunctionDerivationLogicConfig = FunctionDerivationBase & DebouncedDerivationTrigger;
1094
1714
  /**
1095
1715
  * Configuration for value derivation logic.
1096
1716
  *
@@ -1151,7 +1771,7 @@ interface DebouncedDerivationLogicConfig extends BaseDerivationLogicConfig {
1151
1771
  *
1152
1772
  * @public
1153
1773
  */
1154
- type DerivationLogicConfig = OnChangeDerivationLogicConfig | DebouncedDerivationLogicConfig;
1774
+ type DerivationLogicConfig = OnChangeHttpDerivationLogicConfig | DebouncedHttpDerivationLogicConfig | OnChangeAsyncFunctionDerivationLogicConfig | DebouncedAsyncFunctionDerivationLogicConfig | OnChangeExpressionDerivationLogicConfig | DebouncedExpressionDerivationLogicConfig | OnChangeValueDerivationLogicConfig | DebouncedValueDerivationLogicConfig | OnChangeFunctionDerivationLogicConfig | DebouncedFunctionDerivationLogicConfig;
1155
1775
  /**
1156
1776
  * Base configuration for property derivation logic.
1157
1777
  *
@@ -1280,55 +1900,20 @@ interface DebouncedPropertyDerivationLogicConfig extends BasePropertyDerivationL
1280
1900
  /**
1281
1901
  * Configuration for property derivation logic.
1282
1902
  *
1283
- * Enables reactive derivation of field properties (like `minDate`, `options`,
1284
- * `label`, `placeholder`) based on form values and external data.
1285
- *
1286
- * Property derivations are self-targeting: the logic is placed on the field
1287
- * whose property should be derived.
1288
- *
1289
- * @example
1290
- * ```typescript
1291
- * // Derive endDate's minDate from startDate value
1292
- * {
1293
- * key: 'endDate',
1294
- * type: 'datepicker',
1295
- * logic: [{
1296
- * type: 'propertyDerivation',
1297
- * targetProperty: 'minDate',
1298
- * expression: 'formValue.startDate'
1299
- * }]
1300
- * }
1903
+ * @deprecated Use `DerivationLogicConfig` with `targetProperty` instead.
1904
+ * The unified `type: 'derivation'` with `targetProperty` provides the same
1905
+ * functionality with a simpler API surface.
1301
1906
  *
1302
- * // Derive options from another field's value
1303
- * {
1304
- * key: 'city',
1305
- * type: 'select',
1306
- * logic: [{
1307
- * type: 'propertyDerivation',
1308
- * targetProperty: 'options',
1309
- * functionName: 'getCitiesForCountry',
1310
- * dependsOn: ['country']
1311
- * }]
1312
- * }
1313
- *
1314
- * // Derive label conditionally
1315
- * {
1316
- * key: 'phone',
1317
- * type: 'input',
1318
- * logic: [{
1319
- * type: 'propertyDerivation',
1320
- * targetProperty: 'label',
1321
- * value: 'Mobile Phone',
1322
- * condition: {
1323
- * type: 'fieldValue',
1324
- * fieldPath: 'contactType',
1325
- * operator: 'equals',
1326
- * value: 'mobile'
1327
- * }
1328
- * }]
1329
- * }
1907
+ * ```typescript
1908
+ * // Before (deprecated)
1909
+ * { type: 'propertyDerivation', targetProperty: 'minDate', expression: '...' }
1910
+ *
1911
+ * // After (preferred)
1912
+ * { type: 'derivation', targetProperty: 'minDate', expression: '...' }
1330
1913
  * ```
1331
1914
  *
1915
+ * Will be removed in a future minor version.
1916
+ *
1332
1917
  * @public
1333
1918
  */
1334
1919
  type PropertyDerivationLogicConfig = OnChangePropertyDerivationLogicConfig | DebouncedPropertyDerivationLogicConfig;
@@ -1364,6 +1949,9 @@ declare function isFormStateCondition(condition: StateLogicConfig['condition'] |
1364
1949
  /**
1365
1950
  * Type guard to check if a logic config is a PropertyDerivationLogicConfig.
1366
1951
  *
1952
+ * @deprecated Use `isDerivationLogicConfig(config) && hasTargetProperty(config)` instead.
1953
+ * Will be removed in a future minor version.
1954
+ *
1367
1955
  * @param config - The logic config to check
1368
1956
  * @returns true if the config is for property derivation
1369
1957
  *
@@ -1516,78 +2104,59 @@ declare function resolveSubmitButtonDisabled(ctx: ButtonLogicContext): Signal<bo
1516
2104
  */
1517
2105
  declare function resolveNextButtonDisabled(ctx: ButtonLogicContext): Signal<boolean>;
1518
2106
  /**
1519
- * Resolves the hidden state for non-form-bound elements (buttons, text fields, etc.).
2107
+ * Evaluates the hidden state for non-form-bound elements synchronously.
1520
2108
  *
1521
- * This is a generalized function that can be used by any field mapper (buttons, text fields,
1522
- * or any non-form-bound elements) to evaluate hidden logic. It's particularly useful for
1523
- * elements that don't have a FieldTree but still need conditional visibility.
2109
+ * This is a pure function (no signal allocation) that can be called directly inside
2110
+ * an existing `computed()` block without creating ephemeral signal allocations.
1524
2111
  *
1525
2112
  * The hidden state is determined by (in order of precedence):
1526
2113
  * 1. Explicit `hidden: true` on the field definition
1527
2114
  * 2. Field-level `logic` array with `type: 'hidden'` conditions
1528
2115
  *
1529
2116
  * @param ctx - The context containing form, logic array, and explicit hidden state
1530
- * @returns A computed signal that returns true when the element should be hidden
2117
+ * @returns true when the element should be hidden
1531
2118
  *
1532
- * @example
1533
- * ```typescript
1534
- * // In an array button mapper
1535
- * const hiddenSignal = resolveNonFieldHidden({
1536
- * form: rootFormRegistry.getRootForm()!,
1537
- * fieldLogic: buttonField.logic,
1538
- * explicitValue: buttonField.hidden,
1539
- * formValue: rootFormRegistry.getFormValue(),
1540
- * });
2119
+ * @public
2120
+ */
2121
+ declare function evaluateNonFieldHidden(ctx: NonFieldLogicContext): boolean;
2122
+ /**
2123
+ * Resolves the hidden state for non-form-bound elements as a reactive signal.
1541
2124
  *
1542
- * return computed(() => ({
1543
- * ...baseInputs,
1544
- * hidden: hiddenSignal(),
1545
- * }));
1546
- * ```
2125
+ * Wraps {@link evaluateNonFieldHidden} in a `computed()` for use cases where a standalone
2126
+ * signal is needed. When calling from inside an existing `computed()`, prefer
2127
+ * {@link evaluateNonFieldHidden} directly to avoid ephemeral signal allocation.
1547
2128
  *
1548
- * @example
1549
- * ```typescript
1550
- * // In a text field mapper
1551
- * const hiddenSignal = resolveNonFieldHidden({
1552
- * form: rootFormRegistry.getRootForm()!,
1553
- * fieldLogic: textField.logic,
1554
- * explicitValue: textField.hidden,
1555
- * formValue: rootFormRegistry.getFormValue(),
1556
- * });
1557
- * ```
2129
+ * @param ctx - The context containing form, logic array, and explicit hidden state
2130
+ * @returns A computed signal that returns true when the element should be hidden
1558
2131
  *
1559
2132
  * @public
1560
2133
  */
1561
2134
  declare function resolveNonFieldHidden(ctx: NonFieldLogicContext): Signal<boolean>;
1562
2135
  /**
1563
- * Resolves the disabled state for non-form-bound elements (buttons, text fields, etc.).
2136
+ * Evaluates the disabled state for non-form-bound elements synchronously.
1564
2137
  *
1565
- * This is a generalized function that can be used by any field mapper to evaluate
1566
- * disabled logic. It handles elements that don't have form-level disabled defaults
1567
- * (unlike submit/next buttons which have form-level config).
2138
+ * This is a pure function (no signal allocation) that can be called directly inside
2139
+ * an existing `computed()` block without creating ephemeral signal allocations.
1568
2140
  *
1569
2141
  * The disabled state is determined by (in order of precedence):
1570
2142
  * 1. Explicit `disabled: true` on the field definition
1571
2143
  * 2. Field-level `logic` array with `type: 'disabled'` conditions
1572
2144
  *
1573
2145
  * @param ctx - The context containing form, logic array, and explicit disabled state
1574
- * @returns A computed signal that returns true when the element should be disabled
2146
+ * @returns true when the element should be disabled
1575
2147
  *
1576
- * @example
1577
- * ```typescript
1578
- * // In an array button mapper
1579
- * const disabledSignal = resolveNonFieldDisabled({
1580
- * form: rootFormRegistry.getRootForm()!,
1581
- * fieldLogic: buttonField.logic,
1582
- * explicitValue: buttonField.disabled,
1583
- * formValue: rootFormRegistry.getFormValue(),
1584
- * });
2148
+ * @public
2149
+ */
2150
+ declare function evaluateNonFieldDisabled(ctx: NonFieldLogicContext): boolean;
2151
+ /**
2152
+ * Resolves the disabled state for non-form-bound elements as a reactive signal.
1585
2153
  *
1586
- * return computed(() => ({
1587
- * ...baseInputs,
1588
- * disabled: disabledSignal(),
1589
- * }));
1590
- * ```
2154
+ * Wraps {@link evaluateNonFieldDisabled} in a `computed()` for use cases where a standalone
2155
+ * signal is needed. When calling from inside an existing `computed()`, prefer
2156
+ * {@link evaluateNonFieldDisabled} directly to avoid ephemeral signal allocation.
2157
+ *
2158
+ * @param ctx - The context containing form, logic array, and explicit disabled state
2159
+ * @returns A computed signal that returns true when the element should be disabled
1591
2160
  *
1592
2161
  * @public
1593
2162
  */
@@ -1633,7 +2202,7 @@ interface FieldRegistryContainers {
1633
2202
  page: PageField;
1634
2203
  row: RowField;
1635
2204
  group: GroupField;
1636
- array: ArrayField;
2205
+ array: ArrayField | SimplifiedArrayField;
1637
2206
  }
1638
2207
  /**
1639
2208
  * Leaf fields registry - augment this interface to add custom leaf fields
@@ -1748,18 +2317,28 @@ type UnionToIntersection<U> = (U extends U ? (k: U) => void : never) extends (k:
1748
2317
  */
1749
2318
  type Depth = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1750
2319
  /**
1751
- * Widens literal types to their primitive equivalents.
2320
+ * Widens literal types to their primitive equivalents, recursively for objects and arrays.
1752
2321
  * This prevents `as const` from over-narrowing types like `''` to literal `''` instead of `string`.
1753
2322
  *
2323
+ * Depth-limited to prevent slow type checking on deeply nested `as const` objects.
2324
+ * Falls back to `T` (unwidened) when depth is exhausted.
2325
+ *
2326
+ * Note: For object types, `readonly` modifiers are intentionally stripped (`-readonly`)
2327
+ * so that inferred form value types have mutable properties. This is by design since
2328
+ * `as const` adds `readonly` to all properties, but form values should be mutable.
2329
+ *
1754
2330
  * @example
1755
2331
  * ```typescript
1756
2332
  * type A = Widen<''>; // string
1757
2333
  * type B = Widen<false>; // boolean
1758
2334
  * type C = Widen<42>; // number
1759
2335
  * type D = Widen<string[]>; // string[]
2336
+ * type E = Widen<{ name: 'Jane' }>; // { name: string }
1760
2337
  * ```
1761
2338
  */
1762
- type Widen<T> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : T;
2339
+ type Widen<T, D extends number = 5> = [D] extends [never] ? T : T extends string ? string : T extends number ? number : T extends boolean ? boolean : T extends readonly (infer U)[] ? Widen<U, Depth[D]>[] : T extends Record<string, unknown> ? {
2340
+ -readonly [K in keyof T]: Widen<T[K], Depth[D]>;
2341
+ } : T;
1763
2342
  /**
1764
2343
  * Infer value type based on field type and props.
1765
2344
  * - Slider fields: always number
@@ -1783,6 +2362,21 @@ type MaybeOptional<T, V> = T extends {
1783
2362
  } ? V : T extends {
1784
2363
  required: true;
1785
2364
  } ? V : V | undefined;
2365
+ /**
2366
+ * Infers the value type for an array field.
2367
+ * Handles three cases:
2368
+ * 1. Simplified array with template + value → infer item type from value
2369
+ * 2. Simplified array with template only → unknown[]
2370
+ * 3. Full-API array with fields → infer from children
2371
+ */
2372
+ type InferArrayValue<T, D extends number> = T extends {
2373
+ template: unknown;
2374
+ value: readonly (infer Item)[];
2375
+ } ? Widen<Item>[] : T extends {
2376
+ template: unknown;
2377
+ } ? unknown[] : T extends {
2378
+ fields: infer F;
2379
+ } ? F extends RegisteredFieldTypes[] ? InferFormValueWithDepth<F, Depth[D]>[] : unknown[] : unknown[];
1786
2380
  /**
1787
2381
  * Process a single field and determine its contribution to the form value type
1788
2382
  */
@@ -1800,11 +2394,8 @@ type ProcessField<T, D extends number = 5> = [D] extends [never] ? Record<string
1800
2394
  } : never : T extends {
1801
2395
  type: 'array';
1802
2396
  key: infer K;
1803
- fields: infer F;
1804
- } ? K extends string ? F extends RegisteredFieldTypes[] ? {
1805
- [P in K]: InferFormValueWithDepth<F, Depth[D]>[];
1806
- } : {
1807
- [P in K]: unknown[];
2397
+ } ? K extends string ? {
2398
+ [P in K]: InferArrayValue<T, D>;
1808
2399
  } : never : T extends {
1809
2400
  type: 'text';
1810
2401
  } ? never : T extends {
@@ -1857,6 +2448,31 @@ type ExtractFields<T> = T extends {
1857
2448
  */
1858
2449
  type InferFormValue$1<T> = ExtractFields<T> extends readonly RegisteredFieldTypes[] ? InferFormValueWithDepth<ExtractFields<T> extends RegisteredFieldTypes[] ? ExtractFields<T> : [...ExtractFields<T>], 5> : never;
1859
2450
 
2451
+ /**
2452
+ * Mapping configuration for interpreting HTTP responses as validation results.
2453
+ *
2454
+ * Expressions in `validWhen` and `errorParams` are evaluated with scope `{ response }` only —
2455
+ * they do NOT have access to `formValue`, `fieldValue`, or the full `EvaluationContext`.
2456
+ * This is intentional for v1: response mapping is purely about interpreting the HTTP response.
2457
+ */
2458
+ interface HttpValidationResponseMapping {
2459
+ /**
2460
+ * Expression evaluated with scope `{ response }`. Truthy = valid (no error).
2461
+ *
2462
+ * NOTE: This is the OPPOSITE of the function-based HttpCustomValidator.onSuccess
2463
+ * convention, which maps successful HTTP responses to validation errors.
2464
+ * Here, truthy means "validation passed".
2465
+ */
2466
+ validWhen: string;
2467
+ /** Error kind returned when validation fails — maps to field-level `validationMessages` */
2468
+ errorKind: string;
2469
+ /**
2470
+ * Parameters to include in the validation error for message interpolation.
2471
+ * Map of parameter names to expressions evaluated against `{ response }`.
2472
+ */
2473
+ errorParams?: Record<string, string>;
2474
+ }
2475
+
1860
2476
  /**
1861
2477
  * Base configuration shared by all validators
1862
2478
  */
@@ -1908,34 +2524,80 @@ interface CustomValidatorConfig extends BaseValidatorConfig {
1908
2524
  errorParams?: Record<string, string>;
1909
2525
  }
1910
2526
  /**
1911
- * Async custom validator configuration using Angular's validateAsync API
1912
- * Returns Observable<ValidationError | ValidationError[] | null>
2527
+ * Async custom validator configuration using Angular's validateAsync API.
2528
+ * Returns Observable<ValidationError | ValidationError[] | null>.
2529
+ *
2530
+ * Accepts both `'async'` (preferred) and `'customAsync'` (deprecated) type literals.
1913
2531
  */
1914
2532
  interface AsyncValidatorConfig extends BaseValidatorConfig {
1915
- /** Validator type identifier */
1916
- type: 'customAsync';
2533
+ /**
2534
+ * Validator type identifier.
2535
+ *
2536
+ * Use `'async'` for new code. `'customAsync'` is accepted for backward compatibility
2537
+ * but emits a deprecation warning in dev mode.
2538
+ */
2539
+ type: 'async' | 'customAsync';
1917
2540
  /** Name of registered async validator function */
1918
2541
  functionName: string;
1919
2542
  /** Optional parameters to pass to validator function */
1920
2543
  params?: Record<string, unknown>;
1921
2544
  }
1922
2545
  /**
1923
- * HTTP validator configuration using Angular's validateHttp API
1924
- * Provides optimized HTTP validation with automatic request cancellation
2546
+ * Function-based HTTP validator configuration — requires a registered function.
2547
+ *
2548
+ * Uses Angular's `validateHttp` API. The function is registered via
2549
+ * `customFnConfig.httpValidators`.
2550
+ *
2551
+ * Discriminated from `DeclarativeHttpValidatorConfig` by the presence of `functionName`.
2552
+ *
2553
+ * Accepts both `'http'` (preferred) and `'customHttp'` (deprecated) type literals.
2554
+ *
2555
+ * @deprecated Prefer `DeclarativeHttpValidatorConfig` (`type: 'http'` with `http` + `responseMapping`)
2556
+ * for fully JSON-serializable validation. Use this form only when function registration is required.
1925
2557
  */
1926
- interface HttpValidatorConfig extends BaseValidatorConfig {
1927
- /** Validator type identifier */
1928
- type: 'customHttp';
2558
+ interface FunctionHttpValidatorConfig extends BaseValidatorConfig {
2559
+ /**
2560
+ * Validator type identifier.
2561
+ *
2562
+ * Use `'http'` for new code. `'customHttp'` is accepted for backward compatibility
2563
+ * but emits a deprecation warning in dev mode.
2564
+ */
2565
+ type: 'http' | 'customHttp';
1929
2566
  /** Name of registered HTTP validator configuration */
1930
2567
  functionName: string;
1931
2568
  /** Optional parameters to pass to HTTP validator */
1932
2569
  params?: Record<string, unknown>;
1933
2570
  }
1934
2571
  /**
1935
- * Configuration for signal forms validator functions that can be serialized from API
1936
- * Discriminated union type for type-safe validator configuration
2572
+ * @deprecated Use `FunctionHttpValidatorConfig` instead. Will be removed in a future minor version.
2573
+ */
2574
+ type HttpValidatorConfig = FunctionHttpValidatorConfig;
2575
+ /**
2576
+ * Declarative HTTP validator configuration — fully JSON-serializable, no function registration required.
2577
+ *
2578
+ * Uses `HttpRequestConfig` to define the HTTP request and `HttpValidationResponseMapping`
2579
+ * to interpret the response as a validation result. Powered by Angular's `validateHttp` API.
2580
+ *
2581
+ * Discriminated from `FunctionHttpValidatorConfig` by the presence of `http` + `responseMapping`
2582
+ * (and absence of `functionName`).
2583
+ */
2584
+ interface DeclarativeHttpValidatorConfig extends BaseValidatorConfig {
2585
+ /** Validator type identifier */
2586
+ type: 'http';
2587
+ /** HTTP request configuration with expression-based query params and body */
2588
+ http: HttpRequestConfig;
2589
+ /** Mapping that interprets the HTTP response as a validation result */
2590
+ responseMapping: HttpValidationResponseMapping;
2591
+ }
2592
+ /**
2593
+ * Configuration for signal forms validator functions that can be serialized from API.
2594
+ * Discriminated union type for type-safe validator configuration.
2595
+ *
2596
+ * Note: `FunctionHttpValidatorConfig` and `DeclarativeHttpValidatorConfig` both use `type: 'http'`.
2597
+ * They are discriminated by property presence: `functionName` → function-based, `http` → declarative.
2598
+ * Use `isFunctionHttpValidator()` for type-safe narrowing when `type` alone is insufficient.
1937
2599
  */
1938
- type ValidatorConfig = BuiltInValidatorConfig | CustomValidatorConfig | AsyncValidatorConfig | HttpValidatorConfig;
2600
+ type ValidatorConfig = BuiltInValidatorConfig | CustomValidatorConfig | AsyncValidatorConfig | FunctionHttpValidatorConfig | DeclarativeHttpValidatorConfig;
1939
2601
 
1940
2602
  /**
1941
2603
  * Configuration for applying predefined schemas
@@ -2231,6 +2893,76 @@ interface HttpCustomValidator<TValue = unknown, TResult = unknown> {
2231
2893
  readonly onError?: (error: unknown, ctx: FieldContext<TValue>) => ValidationError$1 | ValidationError$1[] | null;
2232
2894
  }
2233
2895
 
2896
+ /**
2897
+ * Tracks deprecated API usages that have already been warned about to prevent log spam.
2898
+ * Scoped to a single form instance via DI.
2899
+ *
2900
+ * This follows the same pattern as DerivationWarningTracker — DI-scoped rather than
2901
+ * module-scoped to avoid SSR issues where state would be shared across requests.
2902
+ *
2903
+ * @public
2904
+ */
2905
+ interface DeprecationWarningTracker {
2906
+ /** Set of deprecation keys we've already warned about */
2907
+ warnedKeys: Set<string>;
2908
+ }
2909
+
2910
+ /**
2911
+ * Represents the state information of a single form field.
2912
+ *
2913
+ * Used in evaluation contexts to allow expressions and conditions
2914
+ * to reference field state (e.g., `fieldState.touched`, `formFieldState.email.dirty`).
2915
+ *
2916
+ * @public
2917
+ */
2918
+ interface FieldStateInfo {
2919
+ readonly touched: boolean;
2920
+ readonly dirty: boolean;
2921
+ /** Convenience property: equivalent to `!dirty` */
2922
+ readonly pristine: boolean;
2923
+ readonly valid: boolean;
2924
+ readonly invalid: boolean;
2925
+ readonly pending: boolean;
2926
+ /**
2927
+ * Whether the field is currently hidden.
2928
+ *
2929
+ * Note: This is a library-managed property, not a native Angular Signal Forms
2930
+ * property. Returns `false` if the field instance does not expose a `hidden` signal.
2931
+ */
2932
+ readonly hidden: boolean;
2933
+ /**
2934
+ * Whether the field is currently readonly.
2935
+ *
2936
+ * Note: This is a library-managed property, not a native Angular Signal Forms
2937
+ * property. Returns `false` if the field instance does not expose a `readonly` signal.
2938
+ */
2939
+ readonly readonly: boolean;
2940
+ /**
2941
+ * Whether the field is currently disabled.
2942
+ *
2943
+ * Note: This is a library-managed property, not a native Angular Signal Forms
2944
+ * property. Returns `false` if the field instance does not expose a `disabled` signal.
2945
+ */
2946
+ readonly disabled: boolean;
2947
+ }
2948
+ /**
2949
+ * Map of field keys to their state information.
2950
+ *
2951
+ * Used as `formFieldState` in evaluation contexts to access
2952
+ * state of any field in the form by key.
2953
+ *
2954
+ * @public
2955
+ */
2956
+ type FormFieldStateMap = Record<string, FieldStateInfo | undefined>;
2957
+ /**
2958
+ * Field state context for the current field being evaluated.
2959
+ *
2960
+ * Used as `fieldState` in evaluation contexts.
2961
+ *
2962
+ * @public
2963
+ */
2964
+ type FieldStateContext = FieldStateInfo;
2965
+
2234
2966
  interface EvaluationContext<TValue = unknown> {
2235
2967
  /** Current field value */
2236
2968
  fieldValue: TValue;
@@ -2302,6 +3034,43 @@ interface EvaluationContext<TValue = unknown> {
2302
3034
  * ```
2303
3035
  */
2304
3036
  externalData?: Record<string, unknown>;
3037
+ /**
3038
+ * DI-scoped tracker for deprecation warnings.
3039
+ * Used by the condition evaluator to deduplicate deprecation warnings.
3040
+ */
3041
+ deprecationTracker?: DeprecationWarningTracker;
3042
+ /**
3043
+ * State of the current field being evaluated.
3044
+ *
3045
+ * Provides access to field state properties like `touched`, `dirty`, `valid`, etc.
3046
+ * Uses a Proxy for lazy evaluation — properties are only read when accessed.
3047
+ *
3048
+ * @example
3049
+ * ```typescript
3050
+ * // In a JavaScript expression:
3051
+ * condition: {
3052
+ * type: 'javascript',
3053
+ * expression: "fieldState.touched && fieldState.dirty"
3054
+ * }
3055
+ * ```
3056
+ */
3057
+ fieldState?: FieldStateContext;
3058
+ /**
3059
+ * State of all fields in the form, keyed by field key.
3060
+ *
3061
+ * Provides access to any field's state properties by key.
3062
+ * Uses a Proxy for lazy evaluation — field state is only read when accessed.
3063
+ *
3064
+ * @example
3065
+ * ```typescript
3066
+ * // In a JavaScript expression:
3067
+ * condition: {
3068
+ * type: 'javascript',
3069
+ * expression: "formFieldState.email.dirty && formFieldState.email.valid"
3070
+ * }
3071
+ * ```
3072
+ */
3073
+ formFieldState?: FormFieldStateMap;
2305
3074
  /** Allow additional properties for flexible expression evaluation */
2306
3075
  [key: string]: unknown;
2307
3076
  }
@@ -2347,6 +3116,43 @@ interface EvaluationContext<TValue = unknown> {
2347
3116
  */
2348
3117
  type CustomFunction = (context: EvaluationContext) => unknown;
2349
3118
 
3119
+ /**
3120
+ * Async function for derivations — returns any value.
3121
+ *
3122
+ * The function receives the evaluation context and may return a Promise or Observable.
3123
+ * Register functions in `customFnConfig.asyncDerivations`.
3124
+ *
3125
+ * @example
3126
+ * ```typescript
3127
+ * const fetchPrice: AsyncDerivationFunction = async (context) => {
3128
+ * const response = await fetch(`/api/price?product=${context.formValue.productId}`);
3129
+ * const data = await response.json();
3130
+ * return data.price;
3131
+ * };
3132
+ * ```
3133
+ *
3134
+ * @public
3135
+ */
3136
+ type AsyncDerivationFunction = (context: EvaluationContext) => Promise<unknown> | Observable<unknown>;
3137
+ /**
3138
+ * Async function for conditions — returns boolean.
3139
+ *
3140
+ * The function receives the evaluation context and may return a Promise or Observable.
3141
+ * Register functions in `customFnConfig.asyncConditions`.
3142
+ *
3143
+ * @example
3144
+ * ```typescript
3145
+ * const checkPermission: AsyncConditionFunction = async (context) => {
3146
+ * const response = await fetch(`/api/permissions?user=${context.formValue.userId}`);
3147
+ * const data = await response.json();
3148
+ * return data.canEdit;
3149
+ * };
3150
+ * ```
3151
+ *
3152
+ * @public
3153
+ */
3154
+ type AsyncConditionFunction = (context: EvaluationContext) => Promise<boolean> | Observable<boolean>;
3155
+
2350
3156
  /**
2351
3157
  * Re-export Angular's ValidationError for consistency
2352
3158
  * This replaces our custom ValidationError interface
@@ -2853,6 +3659,9 @@ interface CustomFnConfig {
2853
3659
  */
2854
3660
  derivations?: Record<string, CustomFunction>;
2855
3661
  /**
3662
+ * @deprecated Register functions under `derivations` instead. Use `type: 'derivation'`
3663
+ * with `targetProperty` in field logic configs. Will be removed in a future minor version.
3664
+ *
2856
3665
  * Custom property derivation functions for reactive property updates.
2857
3666
  *
2858
3667
  * These functions compute derived values for field properties (like `minDate`,
@@ -2892,6 +3701,60 @@ interface CustomFnConfig {
2892
3701
  * ```
2893
3702
  */
2894
3703
  propertyDerivations?: Record<string, CustomFunction>;
3704
+ /**
3705
+ * Async derivation functions for asynchronous value derivation logic.
3706
+ *
3707
+ * These functions perform asynchronous operations (service calls, complex pipelines)
3708
+ * and return the derived value via a Promise or Observable. They are called when a
3709
+ * `DerivationLogicConfig` references them by `asyncFunctionName`.
3710
+ *
3711
+ * Async derivation functions:
3712
+ * - Receive an `EvaluationContext` with access to `formValue`
3713
+ * - Return a Promise or Observable of the value to set on the target field
3714
+ * - Handle their own I/O (no HttpClient provided — use injected services)
3715
+ * - Require explicit `dependsOn` to avoid triggering on every form change
3716
+ *
3717
+ * @example
3718
+ * ```typescript
3719
+ * asyncDerivations: {
3720
+ * fetchSuggestedPrice: async (context) => {
3721
+ * const response = await fetch(`/api/price?product=${context.formValue.productId}`);
3722
+ * const data = await response.json();
3723
+ * return data.suggestedPrice;
3724
+ * },
3725
+ * lookupAddress: (context) => {
3726
+ * return addressService.lookup(context.formValue.zipCode).pipe(
3727
+ * map(result => result.formattedAddress)
3728
+ * );
3729
+ * },
3730
+ * }
3731
+ * ```
3732
+ */
3733
+ asyncDerivations?: Record<string, AsyncDerivationFunction>;
3734
+ /**
3735
+ * Async condition functions for asynchronous field state logic.
3736
+ *
3737
+ * These functions perform asynchronous operations and return a boolean
3738
+ * indicating whether the condition is met. They are referenced by
3739
+ * `asyncFunctionName` in `AsyncCondition` expressions.
3740
+ *
3741
+ * Async condition functions:
3742
+ * - Receive an `EvaluationContext` with access to `formValue`
3743
+ * - Return a Promise or Observable of boolean
3744
+ * - Handle their own I/O (use injected services)
3745
+ *
3746
+ * @example
3747
+ * ```typescript
3748
+ * asyncConditions: {
3749
+ * checkPermission: async (context) => {
3750
+ * const response = await fetch(`/api/permissions?role=${context.formValue.role}`);
3751
+ * const data = await response.json();
3752
+ * return data.canEdit;
3753
+ * },
3754
+ * }
3755
+ * ```
3756
+ */
3757
+ asyncConditions?: Record<string, AsyncConditionFunction>;
2895
3758
  /**
2896
3759
  * Custom validators using Angular's public FieldContext API
2897
3760
  *
@@ -3009,6 +3872,10 @@ interface CustomFnConfig {
3009
3872
  */
3010
3873
  asyncValidators?: Record<string, AsyncCustomValidator>;
3011
3874
  /**
3875
+ * @deprecated Prefer declarative HTTP validators using `type: 'http'` with `http` + `responseMapping`
3876
+ * in the validators array. Function-based HTTP validators now also use `type: 'http'` with `functionName`.
3877
+ * Will be removed in a future minor version.
3878
+ *
3012
3879
  * HTTP validators using Angular's validateHttp() API
3013
3880
  *
3014
3881
  * Angular's validateHttp provides HTTP validation with automatic request
@@ -3150,6 +4017,33 @@ interface FormOptions {
3150
4017
  * ```
3151
4018
  */
3152
4019
  nextButton?: NextButtonOptions;
4020
+ /**
4021
+ * Whether to exclude values of hidden fields from submission output.
4022
+ *
4023
+ * Overrides the global `withValueExclusionDefaults()` setting for this form.
4024
+ * Can be further overridden per-field on individual `FieldDef` entries.
4025
+ *
4026
+ * @default undefined (uses global setting)
4027
+ */
4028
+ excludeValueIfHidden?: boolean;
4029
+ /**
4030
+ * Whether to exclude values of disabled fields from submission output.
4031
+ *
4032
+ * Overrides the global `withValueExclusionDefaults()` setting for this form.
4033
+ * Can be further overridden per-field on individual `FieldDef` entries.
4034
+ *
4035
+ * @default undefined (uses global setting)
4036
+ */
4037
+ excludeValueIfDisabled?: boolean;
4038
+ /**
4039
+ * Whether to exclude values of readonly fields from submission output.
4040
+ *
4041
+ * Overrides the global `withValueExclusionDefaults()` setting for this form.
4042
+ * Can be further overridden per-field on individual `FieldDef` entries.
4043
+ *
4044
+ * @default undefined (uses global setting)
4045
+ */
4046
+ excludeValueIfReadonly?: boolean;
3153
4047
  /**
3154
4048
  * Whether to attach the current form value to all events dispatched through the EventBus.
3155
4049
  *
@@ -3454,6 +4348,9 @@ declare class DynamicForm<TFields extends RegisteredFieldTypes[] = RegisteredFie
3454
4348
  maxDerivationIterations?: number;
3455
4349
  submitButton?: _ng_forge_dynamic_forms.SubmitButtonOptions;
3456
4350
  nextButton?: _ng_forge_dynamic_forms.NextButtonOptions;
4351
+ excludeValueIfHidden?: boolean;
4352
+ excludeValueIfDisabled?: boolean;
4353
+ excludeValueIfReadonly?: boolean;
3457
4354
  emitFormValueOnEvents?: boolean;
3458
4355
  }>;
3459
4356
  /** Field signal context for injection into child components */
@@ -3860,6 +4757,100 @@ declare class NoopLogger implements Logger {
3860
4757
  */
3861
4758
  declare function withEventFormValue(): DynamicFormFeature<'event-form-value'>;
3862
4759
 
4760
+ /**
4761
+ * Configuration for excluding field values from form submission output
4762
+ * based on their reactive state (hidden, disabled, readonly).
4763
+ *
4764
+ * Supports a 3-tier configuration hierarchy: Field > Form > Global.
4765
+ * The most specific level wins for each property.
4766
+ *
4767
+ * @public
4768
+ */
4769
+ interface ValueExclusionConfig {
4770
+ /**
4771
+ * Whether to exclude the value of hidden fields from submission output.
4772
+ *
4773
+ * When `true`, fields whose `hidden()` state is `true` will have their
4774
+ * values omitted from the submitted form value.
4775
+ *
4776
+ * @remarks
4777
+ * This does NOT affect HiddenField (`type: 'hidden'`) — those fields
4778
+ * store values without UI and their `hidden()` state is always `false`.
4779
+ */
4780
+ readonly excludeValueIfHidden?: boolean;
4781
+ /**
4782
+ * Whether to exclude the value of disabled fields from submission output.
4783
+ *
4784
+ * When `true`, fields whose `disabled()` state is `true` will have their
4785
+ * values omitted from the submitted form value.
4786
+ */
4787
+ readonly excludeValueIfDisabled?: boolean;
4788
+ /**
4789
+ * Whether to exclude the value of readonly fields from submission output.
4790
+ *
4791
+ * When `true`, fields whose `readonly()` state is `true` will have their
4792
+ * values omitted from the submitted form value.
4793
+ */
4794
+ readonly excludeValueIfReadonly?: boolean;
4795
+ }
4796
+ /**
4797
+ * Fully resolved exclusion config with all properties required.
4798
+ * Produced by the 3-tier resolution: `field ?? form ?? global`.
4799
+ *
4800
+ * @public
4801
+ */
4802
+ type ResolvedValueExclusionConfig = Required<ValueExclusionConfig>;
4803
+
4804
+ /**
4805
+ * Configures global value exclusion defaults for form submission output.
4806
+ *
4807
+ * Value exclusion is **enabled by default** — field values are excluded from the
4808
+ * `(submitted)` output based on their reactive state. Use this feature to
4809
+ * override those defaults. This does NOT affect two-way binding (`value` model /
4810
+ * `entity`) — fields retain their values internally.
4811
+ *
4812
+ * @example Default behavior (all exclusions enabled)
4813
+ * ```typescript
4814
+ * provideDynamicForm(
4815
+ * ...withMaterialFields(),
4816
+ * withValueExclusionDefaults()
4817
+ * )
4818
+ * ```
4819
+ *
4820
+ * @example Disable specific exclusions
4821
+ * ```typescript
4822
+ * provideDynamicForm(
4823
+ * ...withMaterialFields(),
4824
+ * withValueExclusionDefaults({ excludeValueIfReadonly: false })
4825
+ * )
4826
+ * ```
4827
+ *
4828
+ * @example Disable all exclusions (restore pre-v1 behavior)
4829
+ * ```typescript
4830
+ * provideDynamicForm(
4831
+ * ...withMaterialFields(),
4832
+ * withValueExclusionDefaults({
4833
+ * excludeValueIfHidden: false,
4834
+ * excludeValueIfDisabled: false,
4835
+ * excludeValueIfReadonly: false,
4836
+ * })
4837
+ * )
4838
+ * ```
4839
+ *
4840
+ * @remarks
4841
+ * **Precedence rules:**
4842
+ * 1. Per-field `excludeValueIf*` on `FieldDef` — wins for that field
4843
+ * 2. Per-form `excludeValueIf*` on `FormOptions` — wins for all fields in that form
4844
+ * 3. Global `withValueExclusionDefaults()` — baseline default
4845
+ * 4. No global feature — uses token default (all enabled)
4846
+ *
4847
+ * @param config - Partial override of exclusion rules. Unspecified properties default to `true`.
4848
+ * @returns A DynamicFormFeature that configures value exclusion defaults
4849
+ *
4850
+ * @public
4851
+ */
4852
+ declare function withValueExclusionDefaults(config?: Partial<ValueExclusionConfig>): DynamicFormFeature<'value-exclusion'>;
4853
+
3863
4854
  interface FieldOption<T = unknown> {
3864
4855
  label: DynamicText;
3865
4856
  value: T;
@@ -4060,7 +5051,7 @@ interface BaseValueField<TProps, TValue, TMeta extends FieldMeta = FieldMeta> ex
4060
5051
  required?: boolean;
4061
5052
  }
4062
5053
  declare function isValueField<TProps, TMeta extends FieldMeta = FieldMeta>(field: FieldDef<TProps, TMeta>): field is BaseValueField<TProps, ValueType, TMeta>;
4063
- type ExcludedKeys$1 = 'type' | 'conditionals' | 'value' | 'valueType' | 'disabled' | 'readonly' | 'hidden' | 'col' | 'minValue' | 'maxValue' | 'step' | 'required' | 'email' | 'min' | 'max' | 'minLength' | 'maxLength' | 'pattern' | 'validators' | 'logic' | 'derivation' | 'schemas';
5054
+ type ExcludedKeys$1 = 'type' | 'conditionals' | 'value' | 'valueType' | 'disabled' | 'readonly' | 'hidden' | 'col' | 'minValue' | 'maxValue' | 'step' | 'required' | 'email' | 'min' | 'max' | 'minLength' | 'maxLength' | 'pattern' | 'validators' | 'logic' | 'derivation' | 'schemas' | 'excludeValueIfHidden' | 'excludeValueIfDisabled' | 'excludeValueIfReadonly';
4064
5055
  type ValueFieldComponent<T extends BaseValueField<Record<string, unknown> | unknown, unknown>> = Prettify<WithInputSignals<Omit<T, ExcludedKeys$1>>>;
4065
5056
 
4066
5057
  interface BaseCheckedField<TProps, TMeta extends FieldMeta = FieldMeta> extends FieldDef<TProps, TMeta>, FieldWithValidation {
@@ -4073,7 +5064,7 @@ interface BaseCheckedField<TProps, TMeta extends FieldMeta = FieldMeta> extends
4073
5064
  required?: boolean;
4074
5065
  }
4075
5066
  declare function isCheckedField<TProps, TMeta extends FieldMeta = FieldMeta>(field: FieldDef<TProps, TMeta>): field is BaseCheckedField<TProps, TMeta>;
4076
- type ExcludedKeys = 'type' | 'conditionals' | 'value' | 'disabled' | 'readonly' | 'hidden' | 'col' | keyof FieldWithValidation;
5067
+ type ExcludedKeys = 'type' | 'conditionals' | 'value' | 'disabled' | 'readonly' | 'hidden' | 'col' | keyof FieldWithValidation | 'excludeValueIfHidden' | 'excludeValueIfDisabled' | 'excludeValueIfReadonly';
4077
5068
  type CheckedFieldComponent<T extends BaseCheckedField<Record<string, unknown> | unknown>> = Prettify<WithInputSignals<Omit<T, ExcludedKeys>>>;
4078
5069
 
4079
5070
  declare function applyValidator(config: ValidatorConfig, fieldPath: SchemaPath<any> | SchemaPathTree<any>): void;
@@ -4092,20 +5083,12 @@ declare class PreviousPageEvent implements FormEvent {
4092
5083
  }
4093
5084
 
4094
5085
  /**
4095
- * Template type for OBJECT array items: array of field configurations.
4096
- * Each field's value is merged into the item object.
4097
- */
4098
- type ArrayItemTemplate = ArrayAllowedChildren[];
4099
- /**
4100
- * Template type for array items that can be either:
4101
- * - A single field (ArrayAllowedChildren) for PRIMITIVE items - extracts field value directly
4102
- * - An array of fields (ArrayItemTemplate) for OBJECT items - merges fields into object
4103
- *
4104
- * Examples:
4105
- * - Primitive: `{ key: 'tag', type: 'input', value: 'angular' }` → 'angular'
4106
- * - Object: `[{ key: 'name', type: 'input' }, { key: 'email', type: 'input' }]` → { name: '', email: '' }
5086
+ * Template type for array items used in events.
5087
+ * Canonical definition lives in {@link ArrayItemDefinition} — this alias
5088
+ * preserves the events-specific naming convention.
4107
5089
  */
4108
- type ArrayItemDefinitionTemplate = ArrayAllowedChildren | ArrayItemTemplate;
5090
+ type ArrayItemDefinitionTemplate = ArrayItemDefinition;
5091
+
4109
5092
  /**
4110
5093
  * Event dispatched to append a new item at the END of an array field.
4111
5094
  *
@@ -4759,6 +5742,8 @@ declare function baseFieldMapper(fieldDef: FieldDef<unknown>): Signal<Record<str
4759
5742
  * Row components are layout containers that don't change the form shape.
4760
5743
  * The row component will inject FIELD_SIGNAL_CONTEXT directly.
4761
5744
  *
5745
+ * Supports hidden state resolution via `logic` array or static `hidden` property.
5746
+ *
4762
5747
  * @param fieldDef The row field definition
4763
5748
  * @returns Signal containing Record of input names to values for ngComponentOutlet
4764
5749
  */
@@ -4771,6 +5756,8 @@ declare function rowFieldMapper(fieldDef: RowField): Signal<Record<string, unkno
4771
5756
  * The group component will inject the parent FIELD_SIGNAL_CONTEXT and create
4772
5757
  * a scoped child injector for its nested fields.
4773
5758
  *
5759
+ * Supports hidden state resolution via `logic` array or static `hidden` property.
5760
+ *
4774
5761
  * @param fieldDef The group field definition
4775
5762
  * @returns Signal containing Record of input names to values for ngComponentOutlet
4776
5763
  */
@@ -4783,6 +5770,8 @@ declare function groupFieldMapper(fieldDef: GroupField): Signal<Record<string, u
4783
5770
  * The array component will inject the parent FIELD_SIGNAL_CONTEXT and create
4784
5771
  * a scoped child injector for its array item fields.
4785
5772
  *
5773
+ * Supports hidden state resolution via `logic` array or static `hidden` property.
5774
+ *
4786
5775
  * @param fieldDef The array field definition
4787
5776
  * @returns Signal containing Record of input names to values for ngComponentOutlet
4788
5777
  */
@@ -4794,6 +5783,10 @@ declare function arrayFieldMapper(fieldDef: ArrayField): Signal<Record<string, u
4794
5783
  * Page fields are layout containers that don't modify the form context.
4795
5784
  * The page component will inject FIELD_SIGNAL_CONTEXT directly.
4796
5785
  *
5786
+ * Note: Unlike other container mappers (group, row, array), the page mapper does NOT
5787
+ * resolve hidden logic here. Page visibility is managed by the {@link PageOrchestratorComponent}
5788
+ * which evaluates `ContainerLogicConfig` conditions and controls the `isVisible` input.
5789
+ *
4797
5790
  * @param fieldDef The page field definition
4798
5791
  * @returns Signal containing Record of input names to values for ngComponentOutlet
4799
5792
  */
@@ -4906,6 +5899,7 @@ declare class RowFieldComponent {
4906
5899
  field: _angular_core.InputSignal<RowField<readonly _ng_forge_dynamic_forms.RowAllowedChildren[]>>;
4907
5900
  key: _angular_core.InputSignal<string>;
4908
5901
  className: _angular_core.InputSignal<string | undefined>;
5902
+ hidden: _angular_core.InputSignal<boolean>;
4909
5903
  readonly hostClasses: _angular_core.Signal<string>;
4910
5904
  readonly disabled: _angular_core.Signal<boolean>;
4911
5905
  private readonly rawFieldRegistry;
@@ -4914,7 +5908,7 @@ declare class RowFieldComponent {
4914
5908
  constructor();
4915
5909
  private setupEffects;
4916
5910
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RowFieldComponent, never>;
4917
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<RowFieldComponent, "div[row-field]", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
5911
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<RowFieldComponent, "div[row-field]", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "hidden": { "alias": "hidden"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
4918
5912
  }
4919
5913
 
4920
5914
  /**
@@ -4935,6 +5929,7 @@ declare class GroupFieldComponent<TModel extends Record<string, unknown> = Recor
4935
5929
  field: _angular_core.InputSignal<GroupField<readonly _ng_forge_dynamic_forms.GroupAllowedChildren[]>>;
4936
5930
  key: _angular_core.InputSignal<string>;
4937
5931
  className: _angular_core.InputSignal<string | undefined>;
5932
+ hidden: _angular_core.InputSignal<boolean>;
4938
5933
  readonly hostClasses: _angular_core.Signal<string>;
4939
5934
  private readonly rawFieldRegistry;
4940
5935
  private readonly formSetup;
@@ -4964,7 +5959,7 @@ declare class GroupFieldComponent<TModel extends Record<string, unknown> = Recor
4964
5959
  constructor();
4965
5960
  private setupEffects;
4966
5961
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<GroupFieldComponent<any>, never>;
4967
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<GroupFieldComponent<any>, "fieldset[group-field]", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; }, { "validityChange": "validityChange"; "dirtyChange": "dirtyChange"; "submitted": "submitted"; }, never, never, true, never>;
5962
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<GroupFieldComponent<any>, "fieldset[group-field]", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "hidden": { "alias": "hidden"; "required": false; "isSignal": true; }; }, { "validityChange": "validityChange"; "dirtyChange": "dirtyChange"; "submitted": "submitted"; }, never, never, true, never>;
4968
5963
  }
4969
5964
 
4970
5965
  /**
@@ -5011,14 +6006,40 @@ declare class ArrayFieldComponent<TModel extends Record<string, unknown> = Recor
5011
6006
  field: _angular_core.InputSignal<ArrayField<readonly ArrayItemDefinition[]>>;
5012
6007
  key: _angular_core.InputSignal<string>;
5013
6008
  className: _angular_core.InputSignal<string | undefined>;
6009
+ hidden: _angular_core.InputSignal<boolean>;
5014
6010
  readonly hostClasses: _angular_core.Signal<string>;
5015
6011
  private readonly rawFieldRegistry;
6012
+ /**
6013
+ * Gets the auto-remove button FieldDef from normalization metadata.
6014
+ * Set by simplified array normalization for primitive arrays with remove buttons.
6015
+ * The button is rendered alongside each item without wrapping in a row,
6016
+ * preserving flat primitive form values.
6017
+ */
6018
+ private readonly autoRemoveButton;
6019
+ /**
6020
+ * For primitive array items, the key of the value field template (e.g., 'value').
6021
+ * Used to wrap the FormControl in the item context so getFieldTree(key) works.
6022
+ * Returns undefined for object arrays (FormGroup items have natural child navigation).
6023
+ *
6024
+ * Detection order:
6025
+ * 1. Normalization metadata (for simplified arrays — always available at normalization time)
6026
+ * 2. Existing item definitions (non-empty full-API arrays)
6027
+ * 3. Dynamically discovered key from handleAddFromEvent (empty full-API arrays)
6028
+ *
6029
+ * Uses linkedSignal: recomputes when field() changes, supports manual set()
6030
+ * for the dynamic discovery case.
6031
+ */
6032
+ private readonly primitiveFieldKey;
5016
6033
  /**
5017
6034
  * Gets the item templates (field definitions) for the array.
5018
6035
  * Each element can be either:
5019
6036
  * - A single FieldDef (primitive item) - normalized to [FieldDef]
5020
6037
  * - An array of FieldDefs (object item) - used as-is
5021
6038
  *
6039
+ * When auto-remove is configured, the remove button is appended to each item's
6040
+ * template list for rendering. This is purely visual — the form schema uses the
6041
+ * original primitive item definition (single FieldDef → FormControl → flat value).
6042
+ *
5022
6043
  * Returns normalized templates where all items are arrays for consistent handling.
5023
6044
  */
5024
6045
  private readonly itemTemplates;
@@ -5032,6 +6053,14 @@ declare class ArrayFieldComponent<TModel extends Record<string, unknown> = Recor
5032
6053
  private readonly itemPositionMap;
5033
6054
  /** Read-only view of resolved items for template consumption. */
5034
6055
  readonly resolvedItems: _angular_core.Signal<ResolvedArrayItem[]>;
6056
+ /**
6057
+ * Caches the result of appending the auto-remove button to template arrays.
6058
+ * Keyed by template array reference — cache hits occur during recreate/resolution
6059
+ * operations where stored template references are reused. Add operations via
6060
+ * handleAddFromEvent always create a fresh `[...template]` copy (line ~277),
6061
+ * so each add is a cache miss by design (the spread is needed for mutability).
6062
+ */
6063
+ private readonly autoRemoveCache;
5035
6064
  constructor();
5036
6065
  private setupEffects;
5037
6066
  private setupEventHandlers;
@@ -5056,6 +6085,18 @@ declare class ArrayFieldComponent<TModel extends Record<string, unknown> = Recor
5056
6085
  * 3. Return undefined (item cannot be resolved without a template)
5057
6086
  */
5058
6087
  private createResolveItemObservable;
6088
+ /**
6089
+ * Appends the auto-remove button to a templates array for rendering.
6090
+ * The button is added for visual rendering only — it doesn't affect the form schema.
6091
+ * Original templates are stored in templateRegistry WITHOUT the remove button,
6092
+ * so this method is called during resolution to add it dynamically.
6093
+ *
6094
+ * Uses a WeakMap cache keyed by template array reference. Cache hits occur
6095
+ * during recreate/resolution paths where stored templates are reused.
6096
+ * Add operations always pass a fresh `[...template]` copy, so they miss
6097
+ * the cache intentionally (the copy is needed for mutable item construction).
6098
+ */
6099
+ private withAutoRemove;
5059
6100
  /**
5060
6101
  * Handles remove operations from events (pop, shift, removeAt).
5061
6102
  * Updates resolvedItems FIRST, then form value - this ensures differential
@@ -5064,7 +6105,7 @@ declare class ArrayFieldComponent<TModel extends Record<string, unknown> = Recor
5064
6105
  */
5065
6106
  private removeItem;
5066
6107
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ArrayFieldComponent<any>, never>;
5067
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ArrayFieldComponent<any>, "array-field", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
6108
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ArrayFieldComponent<any>, "array-field", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "hidden": { "alias": "hidden"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
5068
6109
  }
5069
6110
 
5070
6111
  /**
@@ -5150,5 +6191,5 @@ declare class RootFormRegistryService {
5150
6191
  constructor(formValue: Signal<Record<string, unknown>>, rootForm: Signal<FieldTree<Record<string, unknown>> | undefined>);
5151
6192
  }
5152
6193
 
5153
- export { ARRAY_CONTEXT, AppendArrayItemEvent, ArrayFieldComponent, BUILT_IN_FIELDS, ConsoleLogger, DEFAULT_PROPS, DEFAULT_VALIDATION_MESSAGES, DynamicForm, DynamicFormError, DynamicFormLogger, DynamicTextPipe, EventBus, FIELD_REGISTRY, FIELD_SIGNAL_CONTEXT, FORM_OPTIONS, FormClearEvent, FormResetEvent, GroupFieldComponent, InsertArrayItemEvent, NextPageEvent, NoopLogger, PageChangeEvent, PopArrayItemEvent, PrependArrayItemEvent, PreviousPageEvent, RemoveAtIndexEvent, RootFormRegistryService, RowFieldComponent, ShiftArrayItemEvent, SubmitEvent, applyMetaToElement, applyValidator, applyValidators, arrayEvent, arrayFieldMapper, baseFieldMapper, buildBaseInputs, createField, dynamicTextToObservable, field, formConfig, getArrayLength, groupFieldMapper, hasFormValue, interpolateParams, isArrayField, isCheckedField, isContainerField, isDisplayOnlyField, isEqual, isFormStateCondition, isGroupField, isLeafField, isPageField, isPropertyDerivationLogicConfig, isRowField, isValueBearingField, isValueField, omit, pageFieldMapper, provideDynamicForm, resolveNextButtonDisabled, resolveNonFieldDisabled, resolveNonFieldHidden, resolveSubmitButtonDisabled, resolveTokens, rowFieldMapper, textFieldMapper, withEventFormValue, withLoggerConfig };
5154
- export type { ArrayAllowedChildren, ArrayContext, ArrayField, ArrayFieldTree, ArrayItemContext, ArrayItemDefinitionTemplate, ArrayItemTemplate, AsyncCustomValidator, AsyncValidatorConfig, AvailableFieldTypes, BaseCheckedField, BaseValidatorConfig, BaseValueField, BuiltInValidatorConfig, ButtonLogicContext, CheckedFieldComponent, ConditionalExpression, ContainerFieldTypes, CustomFnConfig, CustomValidator, CustomValidatorConfig, DynamicFormFieldRegistry, DynamicText, EvaluationContext, ExtractField, ExtractFieldDefs, ExtractFormValue, FieldComponent, FieldDef, FieldMeta, FieldOption, FieldPathAccess, FieldRegistryContainers, FieldRegistryLeaves, FieldSignalContext, FieldTypeDefinition, FieldWithValidation, FormConfig, FormEvent, FormEventConstructor, FormMode, FormModeDetectionResult, FormOptions, FormStateCondition, GroupAllowedChildren, GroupField, HttpCustomValidator, HttpResourceRequest, HttpValidatorConfig, InferFormValue$1 as InferFormValue, LeafFieldTypes, Logger, LogicConfig, MapperFn, NarrowField, NarrowFields, NextButtonOptions, NonFieldLogicConfig, NonFieldLogicContext, NonFieldLogicType, PageAllowedChildren, PageField, Prettify, PropertyDerivationLogicConfig, RegisteredFieldTypes, RowAllowedChildren, RowField, SchemaApplicationConfig, SchemaDefinition, StateLogicConfig, SubmissionActionResult, SubmissionConfig, SubmitButtonOptions, TextElementType, TextField, TextProps, TokenContext, ValidationError, ValidationMessages, ValidatorConfig, ValueFieldComponent, ValueHandlingMode, ValueType, WithInputSignals };
6194
+ export { ARRAY_CONTEXT, AppendArrayItemEvent, ArrayFieldComponent, BUILT_IN_FIELDS, ConsoleLogger, DEFAULT_PROPS, DEFAULT_VALIDATION_MESSAGES, DynamicForm, DynamicFormError, DynamicFormLogger, DynamicTextPipe, EventBus, FIELD_REGISTRY, FIELD_SIGNAL_CONTEXT, FORM_OPTIONS, FormClearEvent, FormResetEvent, GroupFieldComponent, InsertArrayItemEvent, NextPageEvent, NoopLogger, PageChangeEvent, PopArrayItemEvent, PrependArrayItemEvent, PreviousPageEvent, RemoveAtIndexEvent, RootFormRegistryService, RowFieldComponent, ShiftArrayItemEvent, SubmitEvent, applyMetaToElement, applyValidator, applyValidators, arrayEvent, arrayFieldMapper, baseFieldMapper, buildBaseInputs, createField, dynamicTextToObservable, evaluateNonFieldDisabled, evaluateNonFieldHidden, field, formConfig, getArrayLength, groupFieldMapper, hasFormValue, interpolateParams, isArrayField, isCheckedField, isContainerField, isDisplayOnlyField, isEqual, isFormStateCondition, isGroupField, isLeafField, isPageField, isPropertyDerivationLogicConfig, isRowField, isSimplifiedArrayField, isValueBearingField, isValueField, omit, pageFieldMapper, provideDynamicForm, resolveNextButtonDisabled, resolveNonFieldDisabled, resolveNonFieldHidden, resolveSubmitButtonDisabled, resolveTokens, rowFieldMapper, textFieldMapper, withEventFormValue, withLoggerConfig, withValueExclusionDefaults };
6195
+ export type { ArrayAllowedChildren, ArrayButtonConfig, ArrayContext, ArrayField, ArrayFieldTree, ArrayItemContext, ArrayItemDefinitionTemplate, ArrayItemTemplate, AsyncCondition, AsyncConditionFunction, AsyncCustomValidator, AsyncDerivationFunction, AsyncValidatorConfig, AvailableFieldTypes, BaseCheckedField, BaseValidatorConfig, BaseValueField, BuiltInValidatorConfig, ButtonLogicContext, CheckedFieldComponent, ConditionalExpression, ContainerFieldTypes, CustomFnConfig, CustomValidator, CustomValidatorConfig, DeclarativeHttpValidatorConfig, DynamicFormFieldRegistry, DynamicText, EvaluationContext, ExtractField, ExtractFieldDefs, ExtractFormValue, FieldComponent, FieldDef, FieldMeta, FieldOption, FieldPathAccess, FieldRegistryContainers, FieldRegistryLeaves, FieldSignalContext, FieldStateContext, FieldStateInfo, FieldTypeDefinition, FieldWithValidation, FormConfig, FormEvent, FormEventConstructor, FormFieldStateMap, FormMode, FormModeDetectionResult, FormOptions, FormStateCondition, GroupAllowedChildren, GroupField, HttpCondition, HttpCustomValidator, HttpRequestConfig, HttpResourceRequest, HttpValidationResponseMapping, HttpValidatorConfig, InferFormValue$1 as InferFormValue, LeafFieldTypes, Logger, LogicConfig, MapperFn, NarrowField, NarrowFields, NextButtonOptions, NonFieldLogicConfig, NonFieldLogicContext, NonFieldLogicType, PageAllowedChildren, PageField, Prettify, PropertyDerivationLogicConfig, RegisteredFieldTypes, ResolvedValueExclusionConfig, RowAllowedChildren, RowField, SchemaApplicationConfig, SchemaDefinition, SimplifiedArrayField, StateLogicConfig, SubmissionActionResult, SubmissionConfig, SubmitButtonOptions, TextElementType, TextField, TextProps, TokenContext, ValidationError, ValidationMessages, ValidatorConfig, ValueExclusionConfig, ValueFieldComponent, ValueHandlingMode, ValueType, WithInputSignals };