@ng-forge/dynamic-forms 0.5.2 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -9
- package/fesm2022/{ng-forge-dynamic-forms-ng-forge-dynamic-forms-9JM7tFkl.mjs → ng-forge-dynamic-forms-ng-forge-dynamic-forms-DXXp5M0q.mjs} +3577 -811
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-DXXp5M0q.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-D6M_uJKu.mjs +109 -0
- package/fesm2022/{ng-forge-dynamic-forms-page-field.component-Bm1KS0M6.mjs.map → ng-forge-dynamic-forms-page-field.component-D6M_uJKu.mjs.map} +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-DmJwXtzI.mjs → ng-forge-dynamic-forms-text-field.component-Ael-STTb.mjs} +5 -5
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-DmJwXtzI.mjs.map → ng-forge-dynamic-forms-text-field.component-Ael-STTb.mjs.map} +1 -1
- package/fesm2022/ng-forge-dynamic-forms.mjs +1 -1
- package/package.json +4 -4
- package/types/ng-forge-dynamic-forms.d.ts +1498 -347
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-9JM7tFkl.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-Bm1KS0M6.mjs +0 -109
|
@@ -3,7 +3,7 @@ import { Observable } from 'rxjs';
|
|
|
3
3
|
import * as _angular_core from '@angular/core';
|
|
4
4
|
import { Signal, Injector, WritableSignal, InjectionToken, Type, ResourceRef, Provider, EnvironmentProviders, PipeTransform } from '@angular/core';
|
|
5
5
|
import * as _angular_forms_signals from '@angular/forms/signals';
|
|
6
|
-
import { FieldTree, FieldContext, ValidationError as ValidationError$1,
|
|
6
|
+
import { FieldTree, FieldContext, TreeValidationResult, ValidationError as ValidationError$1, SchemaPath, SchemaPathTree } from '@angular/forms/signals';
|
|
7
7
|
import * as _angular_forms from '@angular/forms';
|
|
8
8
|
import * as _ng_forge_dynamic_forms from '@ng-forge/dynamic-forms';
|
|
9
9
|
import { FormSchema } from '@ng-forge/dynamic-forms/schema';
|
|
@@ -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
|
|
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
|
|
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
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
/**
|
|
684
|
-
|
|
685
|
-
/**
|
|
686
|
-
|
|
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
|
-
*
|
|
697
|
-
*
|
|
698
|
-
*
|
|
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
|
|
701
|
-
|
|
702
|
-
type: 'hidden';
|
|
1020
|
+
interface SimplifiedArrayField extends FieldDef<never> {
|
|
1021
|
+
type: 'array';
|
|
703
1022
|
/**
|
|
704
|
-
*
|
|
705
|
-
*
|
|
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
|
-
|
|
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?:
|
|
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
|
-
*
|
|
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
|
|
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,27 +1368,182 @@ interface BaseDerivationLogicConfig {
|
|
|
976
1368
|
*/
|
|
977
1369
|
condition?: ConditionalExpression | boolean;
|
|
978
1370
|
/**
|
|
979
|
-
*
|
|
1371
|
+
* When true, the derivation stops running after the user manually
|
|
1372
|
+
* edits the target field.
|
|
980
1373
|
*
|
|
981
|
-
*
|
|
982
|
-
*
|
|
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
|
-
*
|
|
987
|
-
*
|
|
988
|
-
*
|
|
989
|
-
*
|
|
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
|
-
|
|
1394
|
+
stopOnUserOverride?: boolean;
|
|
1395
|
+
/**
|
|
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.
|
|
1399
|
+
*
|
|
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.
|
|
1403
|
+
*
|
|
1404
|
+
* @example
|
|
1405
|
+
* ```typescript
|
|
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
|
+
* }
|
|
1417
|
+
* ```
|
|
1418
|
+
*/
|
|
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';
|
|
1442
|
+
/**
|
|
1443
|
+
* HTTP request configuration for server-driven derivations.
|
|
1444
|
+
*
|
|
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.
|
|
1449
|
+
*
|
|
1450
|
+
* @example
|
|
1451
|
+
* ```typescript
|
|
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
|
+
* }
|
|
1469
|
+
* ```
|
|
1470
|
+
*/
|
|
1471
|
+
http: HttpRequestConfig;
|
|
1472
|
+
/**
|
|
1473
|
+
* Explicit field dependencies. Required for HTTP derivations to prevent
|
|
1474
|
+
* wildcard triggering on every keystroke.
|
|
1475
|
+
*/
|
|
1476
|
+
dependsOn: string[];
|
|
1477
|
+
/**
|
|
1478
|
+
* Expression to extract the derived value from the HTTP response.
|
|
1479
|
+
*
|
|
1480
|
+
* Evaluated via `ExpressionParser` with `{ response }` as the evaluation scope.
|
|
1481
|
+
*
|
|
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`.
|
|
1508
|
+
*
|
|
1509
|
+
* @example
|
|
1510
|
+
* ```typescript
|
|
1511
|
+
* {
|
|
1512
|
+
* key: 'suggestedPrice',
|
|
1513
|
+
* logic: [{
|
|
1514
|
+
* type: 'derivation',
|
|
1515
|
+
* source: 'asyncFunction',
|
|
1516
|
+
* asyncFunctionName: 'fetchSuggestedPrice',
|
|
1517
|
+
* dependsOn: ['productId', 'quantity'],
|
|
1518
|
+
* }]
|
|
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;
|
|
993
1541
|
/**
|
|
994
1542
|
* JavaScript expression to evaluate for the derived value.
|
|
995
1543
|
*
|
|
996
1544
|
* Has access to `formValue` object containing all form values.
|
|
997
1545
|
* For array fields, `formValue` is scoped to the current array item.
|
|
998
1546
|
* Uses the same secure AST-based parser as other expressions.
|
|
999
|
-
* Mutually exclusive with `value` and `functionName`.
|
|
1000
1547
|
*
|
|
1001
1548
|
* @example
|
|
1002
1549
|
* ```typescript
|
|
@@ -1005,13 +1552,79 @@ interface BaseDerivationLogicConfig {
|
|
|
1005
1552
|
* expression: 'formValue.price * (1 - formValue.discount / 100)'
|
|
1006
1553
|
* ```
|
|
1007
1554
|
*/
|
|
1008
|
-
expression
|
|
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
|
|
1564
|
+
* // Override automatic detection for complex expressions
|
|
1565
|
+
* {
|
|
1566
|
+
* key: 'total',
|
|
1567
|
+
* logic: [{
|
|
1568
|
+
* type: 'derivation',
|
|
1569
|
+
* expression: 'calculateTotal(formValue)',
|
|
1570
|
+
* dependsOn: ['quantity', 'unitPrice', 'discount']
|
|
1571
|
+
* }]
|
|
1572
|
+
* }
|
|
1573
|
+
* ```
|
|
1574
|
+
*/
|
|
1575
|
+
dependsOn?: string[];
|
|
1576
|
+
value?: never;
|
|
1577
|
+
functionName?: never;
|
|
1578
|
+
http?: never;
|
|
1579
|
+
asyncFunctionName?: never;
|
|
1580
|
+
responseExpression?: never;
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* Base for value derivations.
|
|
1584
|
+
*
|
|
1585
|
+
* @internal
|
|
1586
|
+
*/
|
|
1587
|
+
interface ValueDerivationBase extends SharedDerivationFields {
|
|
1588
|
+
source?: never;
|
|
1589
|
+
/**
|
|
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
|
+
* ```
|
|
1601
|
+
*/
|
|
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;
|
|
1615
|
+
}
|
|
1616
|
+
/**
|
|
1617
|
+
* Base for custom sync function derivations.
|
|
1618
|
+
*
|
|
1619
|
+
* @internal
|
|
1620
|
+
*/
|
|
1621
|
+
interface FunctionDerivationBase extends SharedDerivationFields {
|
|
1622
|
+
source?: never;
|
|
1009
1623
|
/**
|
|
1010
1624
|
* Name of a registered custom derivation function.
|
|
1011
1625
|
*
|
|
1012
1626
|
* The function receives the evaluation context and returns the derived value.
|
|
1013
1627
|
* Register functions in `customFnConfig.derivations`.
|
|
1014
|
-
* Mutually exclusive with `value` and `expression`.
|
|
1015
1628
|
*
|
|
1016
1629
|
* @example
|
|
1017
1630
|
* ```typescript
|
|
@@ -1020,17 +1633,13 @@ interface BaseDerivationLogicConfig {
|
|
|
1020
1633
|
* functionName: 'formatPhoneNumber'
|
|
1021
1634
|
* ```
|
|
1022
1635
|
*/
|
|
1023
|
-
functionName
|
|
1636
|
+
functionName: string;
|
|
1024
1637
|
/**
|
|
1025
|
-
* Explicit field dependencies for derivations.
|
|
1026
|
-
*
|
|
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.
|
|
1638
|
+
* Explicit field dependencies for function derivations.
|
|
1030
1639
|
*
|
|
1031
|
-
* If not provided
|
|
1032
|
-
*
|
|
1033
|
-
*
|
|
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.
|
|
1034
1643
|
*
|
|
1035
1644
|
* @example
|
|
1036
1645
|
* ```typescript
|
|
@@ -1043,54 +1652,65 @@ interface BaseDerivationLogicConfig {
|
|
|
1043
1652
|
* dependsOn: ['country']
|
|
1044
1653
|
* }]
|
|
1045
1654
|
* }
|
|
1046
|
-
*
|
|
1047
|
-
* // Override automatic detection for complex expressions
|
|
1048
|
-
* {
|
|
1049
|
-
* key: 'total',
|
|
1050
|
-
* logic: [{
|
|
1051
|
-
* type: 'derivation',
|
|
1052
|
-
* expression: 'calculateTotal(formValue)',
|
|
1053
|
-
* dependsOn: ['quantity', 'unitPrice', 'discount']
|
|
1054
|
-
* }]
|
|
1055
|
-
* }
|
|
1056
1655
|
* ```
|
|
1057
1656
|
*/
|
|
1058
1657
|
dependsOn?: string[];
|
|
1658
|
+
value?: never;
|
|
1659
|
+
expression?: never;
|
|
1660
|
+
http?: never;
|
|
1661
|
+
asyncFunctionName?: never;
|
|
1662
|
+
responseExpression?: never;
|
|
1059
1663
|
}
|
|
1060
1664
|
/**
|
|
1061
|
-
*
|
|
1062
|
-
*
|
|
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).
|
|
1063
1696
|
* @internal
|
|
1064
1697
|
*/
|
|
1065
|
-
|
|
1066
|
-
/**
|
|
1067
|
-
* Trigger for immediate evaluation.
|
|
1068
|
-
* @default 'onChange'
|
|
1069
|
-
*/
|
|
1070
|
-
trigger?: 'onChange';
|
|
1071
|
-
/** Not allowed for onChange trigger */
|
|
1072
|
-
debounceMs?: never;
|
|
1073
|
-
}
|
|
1698
|
+
type OnChangeValueDerivationLogicConfig = ValueDerivationBase & ImmediateDerivationTrigger;
|
|
1074
1699
|
/**
|
|
1075
|
-
*
|
|
1076
|
-
*
|
|
1077
|
-
* Use this for self-transforms (lowercase, trim, format) to avoid
|
|
1078
|
-
* interrupting the user while they're actively typing.
|
|
1079
|
-
*
|
|
1700
|
+
* Value derivation that evaluates after a debounce period.
|
|
1080
1701
|
* @internal
|
|
1081
1702
|
*/
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
}
|
|
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 =
|
|
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
|
-
*
|
|
1284
|
-
* `
|
|
1903
|
+
* @deprecated Use `DerivationLogicConfig` with `targetProperty` instead.
|
|
1904
|
+
* The unified `type: 'derivation'` with `targetProperty` provides the same
|
|
1905
|
+
* functionality with a simpler API surface.
|
|
1285
1906
|
*
|
|
1286
|
-
* Property derivations are self-targeting: the logic is placed on the field
|
|
1287
|
-
* whose property should be derived.
|
|
1288
|
-
*
|
|
1289
|
-
* @example
|
|
1290
1907
|
* ```typescript
|
|
1291
|
-
* //
|
|
1292
|
-
* {
|
|
1293
|
-
* key: 'endDate',
|
|
1294
|
-
* type: 'datepicker',
|
|
1295
|
-
* logic: [{
|
|
1296
|
-
* type: 'propertyDerivation',
|
|
1297
|
-
* targetProperty: 'minDate',
|
|
1298
|
-
* expression: 'formValue.startDate'
|
|
1299
|
-
* }]
|
|
1300
|
-
* }
|
|
1301
|
-
*
|
|
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
|
-
* }
|
|
1908
|
+
* // Before (deprecated)
|
|
1909
|
+
* { type: 'propertyDerivation', targetProperty: 'minDate', expression: '...' }
|
|
1313
1910
|
*
|
|
1314
|
-
* //
|
|
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
|
-
* }
|
|
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
|
-
*
|
|
2107
|
+
* Evaluates the hidden state for non-form-bound elements synchronously.
|
|
1520
2108
|
*
|
|
1521
|
-
* This is a
|
|
1522
|
-
*
|
|
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
|
|
2117
|
+
* @returns true when the element should be hidden
|
|
1531
2118
|
*
|
|
1532
|
-
* @
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
*
|
|
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
|
-
*
|
|
1543
|
-
*
|
|
1544
|
-
*
|
|
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
|
-
* @
|
|
1549
|
-
*
|
|
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
|
-
*
|
|
2136
|
+
* Evaluates the disabled state for non-form-bound elements synchronously.
|
|
1564
2137
|
*
|
|
1565
|
-
* This is a
|
|
1566
|
-
*
|
|
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
|
|
2146
|
+
* @returns true when the element should be disabled
|
|
1575
2147
|
*
|
|
1576
|
-
* @
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
*
|
|
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
|
-
*
|
|
1587
|
-
*
|
|
1588
|
-
*
|
|
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,38 @@ 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 from a single template field (for primitive arrays).
|
|
2367
|
+
* Mirrors InferValueType logic: slider → number, input[number] → number, else string.
|
|
2368
|
+
*/
|
|
2369
|
+
type InferSingleTemplateValue<T, D extends number> = T extends {
|
|
2370
|
+
type: 'slider';
|
|
2371
|
+
} ? number : T extends {
|
|
2372
|
+
type: 'input';
|
|
2373
|
+
props: {
|
|
2374
|
+
type: 'number';
|
|
2375
|
+
};
|
|
2376
|
+
} ? number : T extends {
|
|
2377
|
+
type: 'checkbox' | 'toggle';
|
|
2378
|
+
} ? boolean : T extends {
|
|
2379
|
+
value: infer V;
|
|
2380
|
+
} ? Widen<V, Depth[D]> : string;
|
|
2381
|
+
/**
|
|
2382
|
+
* Infers the value type for an array field.
|
|
2383
|
+
* Handles four cases:
|
|
2384
|
+
* 1. Simplified array with template + value → infer item type from value
|
|
2385
|
+
* 2. Simplified array with array template (no value) → infer object type from template fields
|
|
2386
|
+
* 3. Simplified array with single-field template (no value) → infer primitive type from template field
|
|
2387
|
+
* 4. Full-API array with fields → infer from children
|
|
2388
|
+
*/
|
|
2389
|
+
type InferArrayValue<T, D extends number> = T extends {
|
|
2390
|
+
template: unknown;
|
|
2391
|
+
value: readonly (infer Item)[];
|
|
2392
|
+
} ? Widen<Item>[] : T extends {
|
|
2393
|
+
template: infer TArr;
|
|
2394
|
+
} ? TArr extends readonly RegisteredFieldTypes[] ? InferFormValueWithDepth<[...TArr], Depth[D]>[] : InferSingleTemplateValue<TArr, D>[] : T extends {
|
|
2395
|
+
fields: infer F;
|
|
2396
|
+
} ? F extends RegisteredFieldTypes[] ? InferFormValueWithDepth<F, Depth[D]>[] : unknown[] : unknown[];
|
|
1786
2397
|
/**
|
|
1787
2398
|
* Process a single field and determine its contribution to the form value type
|
|
1788
2399
|
*/
|
|
@@ -1800,11 +2411,8 @@ type ProcessField<T, D extends number = 5> = [D] extends [never] ? Record<string
|
|
|
1800
2411
|
} : never : T extends {
|
|
1801
2412
|
type: 'array';
|
|
1802
2413
|
key: infer K;
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
[P in K]: InferFormValueWithDepth<F, Depth[D]>[];
|
|
1806
|
-
} : {
|
|
1807
|
-
[P in K]: unknown[];
|
|
2414
|
+
} ? K extends string ? {
|
|
2415
|
+
[P in K]: InferArrayValue<T, D>;
|
|
1808
2416
|
} : never : T extends {
|
|
1809
2417
|
type: 'text';
|
|
1810
2418
|
} ? never : T extends {
|
|
@@ -1857,6 +2465,31 @@ type ExtractFields<T> = T extends {
|
|
|
1857
2465
|
*/
|
|
1858
2466
|
type InferFormValue$1<T> = ExtractFields<T> extends readonly RegisteredFieldTypes[] ? InferFormValueWithDepth<ExtractFields<T> extends RegisteredFieldTypes[] ? ExtractFields<T> : [...ExtractFields<T>], 5> : never;
|
|
1859
2467
|
|
|
2468
|
+
/**
|
|
2469
|
+
* Mapping configuration for interpreting HTTP responses as validation results.
|
|
2470
|
+
*
|
|
2471
|
+
* Expressions in `validWhen` and `errorParams` are evaluated with scope `{ response }` only —
|
|
2472
|
+
* they do NOT have access to `formValue`, `fieldValue`, or the full `EvaluationContext`.
|
|
2473
|
+
* This is intentional for v1: response mapping is purely about interpreting the HTTP response.
|
|
2474
|
+
*/
|
|
2475
|
+
interface HttpValidationResponseMapping {
|
|
2476
|
+
/**
|
|
2477
|
+
* Expression evaluated with scope `{ response }`. Must evaluate to `true` (strict boolean) to be valid.
|
|
2478
|
+
*
|
|
2479
|
+
* NOTE: This is the OPPOSITE of the function-based HttpCustomValidator.onSuccess
|
|
2480
|
+
* convention, which maps successful HTTP responses to validation errors.
|
|
2481
|
+
* Here, `=== true` means "validation passed". Non-boolean results are treated as invalid and trigger a warning.
|
|
2482
|
+
*/
|
|
2483
|
+
validWhen: string;
|
|
2484
|
+
/** Error kind returned when validation fails — maps to field-level `validationMessages` */
|
|
2485
|
+
errorKind: string;
|
|
2486
|
+
/**
|
|
2487
|
+
* Parameters to include in the validation error for message interpolation.
|
|
2488
|
+
* Map of parameter names to expressions evaluated against `{ response }`.
|
|
2489
|
+
*/
|
|
2490
|
+
errorParams?: Record<string, string>;
|
|
2491
|
+
}
|
|
2492
|
+
|
|
1860
2493
|
/**
|
|
1861
2494
|
* Base configuration shared by all validators
|
|
1862
2495
|
*/
|
|
@@ -1908,34 +2541,80 @@ interface CustomValidatorConfig extends BaseValidatorConfig {
|
|
|
1908
2541
|
errorParams?: Record<string, string>;
|
|
1909
2542
|
}
|
|
1910
2543
|
/**
|
|
1911
|
-
* Async custom validator configuration using Angular's validateAsync API
|
|
1912
|
-
* Returns Observable<ValidationError | ValidationError[] | null
|
|
2544
|
+
* Async custom validator configuration using Angular's validateAsync API.
|
|
2545
|
+
* Returns Observable<ValidationError | ValidationError[] | null>.
|
|
2546
|
+
*
|
|
2547
|
+
* Accepts both `'async'` (preferred) and `'customAsync'` (deprecated) type literals.
|
|
1913
2548
|
*/
|
|
1914
2549
|
interface AsyncValidatorConfig extends BaseValidatorConfig {
|
|
1915
|
-
/**
|
|
1916
|
-
|
|
2550
|
+
/**
|
|
2551
|
+
* Validator type identifier.
|
|
2552
|
+
*
|
|
2553
|
+
* Use `'async'` for new code. `'customAsync'` is accepted for backward compatibility
|
|
2554
|
+
* but emits a deprecation warning in dev mode.
|
|
2555
|
+
*/
|
|
2556
|
+
type: 'async' | 'customAsync';
|
|
1917
2557
|
/** Name of registered async validator function */
|
|
1918
2558
|
functionName: string;
|
|
1919
2559
|
/** Optional parameters to pass to validator function */
|
|
1920
2560
|
params?: Record<string, unknown>;
|
|
1921
2561
|
}
|
|
1922
2562
|
/**
|
|
1923
|
-
* HTTP validator configuration
|
|
1924
|
-
*
|
|
2563
|
+
* Function-based HTTP validator configuration — requires a registered function.
|
|
2564
|
+
*
|
|
2565
|
+
* Uses Angular's `validateHttp` API. The function is registered via
|
|
2566
|
+
* `customFnConfig.httpValidators`.
|
|
2567
|
+
*
|
|
2568
|
+
* Discriminated from `DeclarativeHttpValidatorConfig` by the presence of `functionName`.
|
|
2569
|
+
*
|
|
2570
|
+
* Accepts both `'http'` (preferred) and `'customHttp'` (deprecated) type literals.
|
|
2571
|
+
*
|
|
2572
|
+
* @deprecated Prefer `DeclarativeHttpValidatorConfig` (`type: 'http'` with `http` + `responseMapping`)
|
|
2573
|
+
* for fully JSON-serializable validation. Use this form only when function registration is required.
|
|
1925
2574
|
*/
|
|
1926
|
-
interface
|
|
1927
|
-
/**
|
|
1928
|
-
|
|
2575
|
+
interface FunctionHttpValidatorConfig extends BaseValidatorConfig {
|
|
2576
|
+
/**
|
|
2577
|
+
* Validator type identifier.
|
|
2578
|
+
*
|
|
2579
|
+
* Use `'http'` for new code. `'customHttp'` is accepted for backward compatibility
|
|
2580
|
+
* but emits a deprecation warning in dev mode.
|
|
2581
|
+
*/
|
|
2582
|
+
type: 'http' | 'customHttp';
|
|
1929
2583
|
/** Name of registered HTTP validator configuration */
|
|
1930
2584
|
functionName: string;
|
|
1931
2585
|
/** Optional parameters to pass to HTTP validator */
|
|
1932
2586
|
params?: Record<string, unknown>;
|
|
1933
2587
|
}
|
|
1934
2588
|
/**
|
|
1935
|
-
*
|
|
1936
|
-
|
|
2589
|
+
* @deprecated Use `FunctionHttpValidatorConfig` instead. Will be removed in a future minor version.
|
|
2590
|
+
*/
|
|
2591
|
+
type HttpValidatorConfig = FunctionHttpValidatorConfig;
|
|
2592
|
+
/**
|
|
2593
|
+
* Declarative HTTP validator configuration — fully JSON-serializable, no function registration required.
|
|
2594
|
+
*
|
|
2595
|
+
* Uses `HttpRequestConfig` to define the HTTP request and `HttpValidationResponseMapping`
|
|
2596
|
+
* to interpret the response as a validation result. Powered by Angular's `validateHttp` API.
|
|
2597
|
+
*
|
|
2598
|
+
* Discriminated from `FunctionHttpValidatorConfig` by the presence of `http` + `responseMapping`
|
|
2599
|
+
* (and absence of `functionName`).
|
|
2600
|
+
*/
|
|
2601
|
+
interface DeclarativeHttpValidatorConfig extends BaseValidatorConfig {
|
|
2602
|
+
/** Validator type identifier */
|
|
2603
|
+
type: 'http';
|
|
2604
|
+
/** HTTP request configuration with expression-based query params and body */
|
|
2605
|
+
http: HttpRequestConfig;
|
|
2606
|
+
/** Mapping that interprets the HTTP response as a validation result */
|
|
2607
|
+
responseMapping: HttpValidationResponseMapping;
|
|
2608
|
+
}
|
|
2609
|
+
/**
|
|
2610
|
+
* Configuration for signal forms validator functions that can be serialized from API.
|
|
2611
|
+
* Discriminated union type for type-safe validator configuration.
|
|
2612
|
+
*
|
|
2613
|
+
* Note: `FunctionHttpValidatorConfig` and `DeclarativeHttpValidatorConfig` both use `type: 'http'`.
|
|
2614
|
+
* They are discriminated by property presence: `functionName` → function-based, `http` → declarative.
|
|
2615
|
+
* Use `isFunctionHttpValidator()` for type-safe narrowing when `type` alone is insufficient.
|
|
1937
2616
|
*/
|
|
1938
|
-
type ValidatorConfig = BuiltInValidatorConfig | CustomValidatorConfig | AsyncValidatorConfig |
|
|
2617
|
+
type ValidatorConfig = BuiltInValidatorConfig | CustomValidatorConfig | AsyncValidatorConfig | FunctionHttpValidatorConfig | DeclarativeHttpValidatorConfig;
|
|
1939
2618
|
|
|
1940
2619
|
/**
|
|
1941
2620
|
* Configuration for applying predefined schemas
|
|
@@ -2231,7 +2910,77 @@ interface HttpCustomValidator<TValue = unknown, TResult = unknown> {
|
|
|
2231
2910
|
readonly onError?: (error: unknown, ctx: FieldContext<TValue>) => ValidationError$1 | ValidationError$1[] | null;
|
|
2232
2911
|
}
|
|
2233
2912
|
|
|
2234
|
-
|
|
2913
|
+
/**
|
|
2914
|
+
* Tracks deprecated API usages that have already been warned about to prevent log spam.
|
|
2915
|
+
* Scoped to a single form instance via DI.
|
|
2916
|
+
*
|
|
2917
|
+
* This follows the same pattern as DerivationWarningTracker — DI-scoped rather than
|
|
2918
|
+
* module-scoped to avoid SSR issues where state would be shared across requests.
|
|
2919
|
+
*
|
|
2920
|
+
* @public
|
|
2921
|
+
*/
|
|
2922
|
+
interface DeprecationWarningTracker {
|
|
2923
|
+
/** Set of deprecation keys we've already warned about */
|
|
2924
|
+
warnedKeys: Set<string>;
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2927
|
+
/**
|
|
2928
|
+
* Represents the state information of a single form field.
|
|
2929
|
+
*
|
|
2930
|
+
* Used in evaluation contexts to allow expressions and conditions
|
|
2931
|
+
* to reference field state (e.g., `fieldState.touched`, `formFieldState.email.dirty`).
|
|
2932
|
+
*
|
|
2933
|
+
* @public
|
|
2934
|
+
*/
|
|
2935
|
+
interface FieldStateInfo {
|
|
2936
|
+
readonly touched: boolean;
|
|
2937
|
+
readonly dirty: boolean;
|
|
2938
|
+
/** Convenience property: equivalent to `!dirty` */
|
|
2939
|
+
readonly pristine: boolean;
|
|
2940
|
+
readonly valid: boolean;
|
|
2941
|
+
readonly invalid: boolean;
|
|
2942
|
+
readonly pending: boolean;
|
|
2943
|
+
/**
|
|
2944
|
+
* Whether the field is currently hidden.
|
|
2945
|
+
*
|
|
2946
|
+
* Note: This is a library-managed property, not a native Angular Signal Forms
|
|
2947
|
+
* property. Returns `false` if the field instance does not expose a `hidden` signal.
|
|
2948
|
+
*/
|
|
2949
|
+
readonly hidden: boolean;
|
|
2950
|
+
/**
|
|
2951
|
+
* Whether the field is currently readonly.
|
|
2952
|
+
*
|
|
2953
|
+
* Note: This is a library-managed property, not a native Angular Signal Forms
|
|
2954
|
+
* property. Returns `false` if the field instance does not expose a `readonly` signal.
|
|
2955
|
+
*/
|
|
2956
|
+
readonly readonly: boolean;
|
|
2957
|
+
/**
|
|
2958
|
+
* Whether the field is currently disabled.
|
|
2959
|
+
*
|
|
2960
|
+
* Note: This is a library-managed property, not a native Angular Signal Forms
|
|
2961
|
+
* property. Returns `false` if the field instance does not expose a `disabled` signal.
|
|
2962
|
+
*/
|
|
2963
|
+
readonly disabled: boolean;
|
|
2964
|
+
}
|
|
2965
|
+
/**
|
|
2966
|
+
* Map of field keys to their state information.
|
|
2967
|
+
*
|
|
2968
|
+
* Used as `formFieldState` in evaluation contexts to access
|
|
2969
|
+
* state of any field in the form by key.
|
|
2970
|
+
*
|
|
2971
|
+
* @public
|
|
2972
|
+
*/
|
|
2973
|
+
type FormFieldStateMap = Record<string, FieldStateInfo | undefined>;
|
|
2974
|
+
/**
|
|
2975
|
+
* Field state context for the current field being evaluated.
|
|
2976
|
+
*
|
|
2977
|
+
* Used as `fieldState` in evaluation contexts.
|
|
2978
|
+
*
|
|
2979
|
+
* @public
|
|
2980
|
+
*/
|
|
2981
|
+
type FieldStateContext = FieldStateInfo;
|
|
2982
|
+
|
|
2983
|
+
interface EvaluationContext<TValue = unknown, TFormValue extends Record<string, unknown> = any> {
|
|
2235
2984
|
/** Current field value */
|
|
2236
2985
|
fieldValue: TValue;
|
|
2237
2986
|
/**
|
|
@@ -2241,7 +2990,7 @@ interface EvaluationContext<TValue = unknown> {
|
|
|
2241
2990
|
* For array item derivations, this is scoped to the current array item.
|
|
2242
2991
|
* Use `rootFormValue` to access the complete form when inside an array context.
|
|
2243
2992
|
*/
|
|
2244
|
-
formValue:
|
|
2993
|
+
formValue: TFormValue;
|
|
2245
2994
|
/** Field path for relative references */
|
|
2246
2995
|
fieldPath: string;
|
|
2247
2996
|
/** Custom evaluation functions */
|
|
@@ -2302,6 +3051,43 @@ interface EvaluationContext<TValue = unknown> {
|
|
|
2302
3051
|
* ```
|
|
2303
3052
|
*/
|
|
2304
3053
|
externalData?: Record<string, unknown>;
|
|
3054
|
+
/**
|
|
3055
|
+
* DI-scoped tracker for deprecation warnings.
|
|
3056
|
+
* Used by the condition evaluator to deduplicate deprecation warnings.
|
|
3057
|
+
*/
|
|
3058
|
+
deprecationTracker?: DeprecationWarningTracker;
|
|
3059
|
+
/**
|
|
3060
|
+
* State of the current field being evaluated.
|
|
3061
|
+
*
|
|
3062
|
+
* Provides access to field state properties like `touched`, `dirty`, `valid`, etc.
|
|
3063
|
+
* Uses a Proxy for lazy evaluation — properties are only read when accessed.
|
|
3064
|
+
*
|
|
3065
|
+
* @example
|
|
3066
|
+
* ```typescript
|
|
3067
|
+
* // In a JavaScript expression:
|
|
3068
|
+
* condition: {
|
|
3069
|
+
* type: 'javascript',
|
|
3070
|
+
* expression: "fieldState.touched && fieldState.dirty"
|
|
3071
|
+
* }
|
|
3072
|
+
* ```
|
|
3073
|
+
*/
|
|
3074
|
+
fieldState?: FieldStateContext;
|
|
3075
|
+
/**
|
|
3076
|
+
* State of all fields in the form, keyed by field key.
|
|
3077
|
+
*
|
|
3078
|
+
* Provides access to any field's state properties by key.
|
|
3079
|
+
* Uses a Proxy for lazy evaluation — field state is only read when accessed.
|
|
3080
|
+
*
|
|
3081
|
+
* @example
|
|
3082
|
+
* ```typescript
|
|
3083
|
+
* // In a JavaScript expression:
|
|
3084
|
+
* condition: {
|
|
3085
|
+
* type: 'javascript',
|
|
3086
|
+
* expression: "formFieldState.email.dirty && formFieldState.email.valid"
|
|
3087
|
+
* }
|
|
3088
|
+
* ```
|
|
3089
|
+
*/
|
|
3090
|
+
formFieldState?: FormFieldStateMap;
|
|
2305
3091
|
/** Allow additional properties for flexible expression evaluation */
|
|
2306
3092
|
[key: string]: unknown;
|
|
2307
3093
|
}
|
|
@@ -2345,7 +3131,44 @@ interface EvaluationContext<TValue = unknown> {
|
|
|
2345
3131
|
* };
|
|
2346
3132
|
* ```
|
|
2347
3133
|
*/
|
|
2348
|
-
type CustomFunction = (context: EvaluationContext) => unknown;
|
|
3134
|
+
type CustomFunction<TFormValue extends Record<string, unknown> = any> = (context: EvaluationContext<unknown, TFormValue>) => unknown;
|
|
3135
|
+
|
|
3136
|
+
/**
|
|
3137
|
+
* Async function for derivations — returns any value.
|
|
3138
|
+
*
|
|
3139
|
+
* The function receives the evaluation context and may return a Promise or Observable.
|
|
3140
|
+
* Register functions in `customFnConfig.asyncDerivations`.
|
|
3141
|
+
*
|
|
3142
|
+
* @example
|
|
3143
|
+
* ```typescript
|
|
3144
|
+
* const fetchPrice: AsyncDerivationFunction = async (context) => {
|
|
3145
|
+
* const response = await fetch(`/api/price?product=${context.formValue.productId}`);
|
|
3146
|
+
* const data = await response.json();
|
|
3147
|
+
* return data.price;
|
|
3148
|
+
* };
|
|
3149
|
+
* ```
|
|
3150
|
+
*
|
|
3151
|
+
* @public
|
|
3152
|
+
*/
|
|
3153
|
+
type AsyncDerivationFunction<TFormValue extends Record<string, unknown> = any> = (context: EvaluationContext<unknown, TFormValue>) => Promise<unknown> | Observable<unknown>;
|
|
3154
|
+
/**
|
|
3155
|
+
* Async function for conditions — returns boolean.
|
|
3156
|
+
*
|
|
3157
|
+
* The function receives the evaluation context and may return a Promise or Observable.
|
|
3158
|
+
* Register functions in `customFnConfig.asyncConditions`.
|
|
3159
|
+
*
|
|
3160
|
+
* @example
|
|
3161
|
+
* ```typescript
|
|
3162
|
+
* const checkPermission: AsyncConditionFunction = async (context) => {
|
|
3163
|
+
* const response = await fetch(`/api/permissions?user=${context.formValue.userId}`);
|
|
3164
|
+
* const data = await response.json();
|
|
3165
|
+
* return data.canEdit;
|
|
3166
|
+
* };
|
|
3167
|
+
* ```
|
|
3168
|
+
*
|
|
3169
|
+
* @public
|
|
3170
|
+
*/
|
|
3171
|
+
type AsyncConditionFunction<TFormValue extends Record<string, unknown> = any> = (context: EvaluationContext<unknown, TFormValue>) => Promise<boolean> | Observable<boolean>;
|
|
2349
3172
|
|
|
2350
3173
|
/**
|
|
2351
3174
|
* Re-export Angular's ValidationError for consistency
|
|
@@ -2610,7 +3433,7 @@ interface FormConfig<TFields extends NarrowFields | RegisteredFieldTypes[] = Reg
|
|
|
2610
3433
|
/**
|
|
2611
3434
|
* Signal forms adapter configuration.
|
|
2612
3435
|
*/
|
|
2613
|
-
customFnConfig?: CustomFnConfig
|
|
3436
|
+
customFnConfig?: CustomFnConfig<TValue extends Record<string, unknown> ? TValue : Record<string, unknown>>;
|
|
2614
3437
|
/**
|
|
2615
3438
|
* Form submission configuration.
|
|
2616
3439
|
*
|
|
@@ -2765,7 +3588,7 @@ interface FormConfig<TFields extends NarrowFields | RegisteredFieldTypes[] = Reg
|
|
|
2765
3588
|
*
|
|
2766
3589
|
* @public
|
|
2767
3590
|
*/
|
|
2768
|
-
interface CustomFnConfig {
|
|
3591
|
+
interface CustomFnConfig<TFormValue extends Record<string, unknown> = Record<string, unknown>> {
|
|
2769
3592
|
/**
|
|
2770
3593
|
* Custom evaluation functions for conditional expressions.
|
|
2771
3594
|
*
|
|
@@ -2783,7 +3606,7 @@ interface CustomFnConfig {
|
|
|
2783
3606
|
* }
|
|
2784
3607
|
* ```
|
|
2785
3608
|
*/
|
|
2786
|
-
customFunctions?: Record<string, CustomFunction
|
|
3609
|
+
customFunctions?: Record<string, CustomFunction<TFormValue>>;
|
|
2787
3610
|
/**
|
|
2788
3611
|
* Custom derivation functions for value derivation logic.
|
|
2789
3612
|
*
|
|
@@ -2851,8 +3674,11 @@ interface CustomFnConfig {
|
|
|
2851
3674
|
* }
|
|
2852
3675
|
* ```
|
|
2853
3676
|
*/
|
|
2854
|
-
derivations?: Record<string, CustomFunction
|
|
3677
|
+
derivations?: Record<string, CustomFunction<TFormValue>>;
|
|
2855
3678
|
/**
|
|
3679
|
+
* @deprecated Register functions under `derivations` instead. Use `type: 'derivation'`
|
|
3680
|
+
* with `targetProperty` in field logic configs. Will be removed in a future minor version.
|
|
3681
|
+
*
|
|
2856
3682
|
* Custom property derivation functions for reactive property updates.
|
|
2857
3683
|
*
|
|
2858
3684
|
* These functions compute derived values for field properties (like `minDate`,
|
|
@@ -2891,7 +3717,61 @@ interface CustomFnConfig {
|
|
|
2891
3717
|
* }
|
|
2892
3718
|
* ```
|
|
2893
3719
|
*/
|
|
2894
|
-
propertyDerivations?: Record<string, CustomFunction
|
|
3720
|
+
propertyDerivations?: Record<string, CustomFunction<TFormValue>>;
|
|
3721
|
+
/**
|
|
3722
|
+
* Async derivation functions for asynchronous value derivation logic.
|
|
3723
|
+
*
|
|
3724
|
+
* These functions perform asynchronous operations (service calls, complex pipelines)
|
|
3725
|
+
* and return the derived value via a Promise or Observable. They are called when a
|
|
3726
|
+
* `DerivationLogicConfig` references them by `asyncFunctionName`.
|
|
3727
|
+
*
|
|
3728
|
+
* Async derivation functions:
|
|
3729
|
+
* - Receive an `EvaluationContext` with access to `formValue`
|
|
3730
|
+
* - Return a Promise or Observable of the value to set on the target field
|
|
3731
|
+
* - Handle their own I/O (no HttpClient provided — use injected services)
|
|
3732
|
+
* - Require explicit `dependsOn` to avoid triggering on every form change
|
|
3733
|
+
*
|
|
3734
|
+
* @example
|
|
3735
|
+
* ```typescript
|
|
3736
|
+
* asyncDerivations: {
|
|
3737
|
+
* fetchSuggestedPrice: async (context) => {
|
|
3738
|
+
* const response = await fetch(`/api/price?product=${context.formValue.productId}`);
|
|
3739
|
+
* const data = await response.json();
|
|
3740
|
+
* return data.suggestedPrice;
|
|
3741
|
+
* },
|
|
3742
|
+
* lookupAddress: (context) => {
|
|
3743
|
+
* return addressService.lookup(context.formValue.zipCode).pipe(
|
|
3744
|
+
* map(result => result.formattedAddress)
|
|
3745
|
+
* );
|
|
3746
|
+
* },
|
|
3747
|
+
* }
|
|
3748
|
+
* ```
|
|
3749
|
+
*/
|
|
3750
|
+
asyncDerivations?: Record<string, AsyncDerivationFunction<TFormValue>>;
|
|
3751
|
+
/**
|
|
3752
|
+
* Async condition functions for asynchronous field state logic.
|
|
3753
|
+
*
|
|
3754
|
+
* These functions perform asynchronous operations and return a boolean
|
|
3755
|
+
* indicating whether the condition is met. They are referenced by
|
|
3756
|
+
* `asyncFunctionName` in `AsyncCondition` expressions.
|
|
3757
|
+
*
|
|
3758
|
+
* Async condition functions:
|
|
3759
|
+
* - Receive an `EvaluationContext` with access to `formValue`
|
|
3760
|
+
* - Return a Promise or Observable of boolean
|
|
3761
|
+
* - Handle their own I/O (use injected services)
|
|
3762
|
+
*
|
|
3763
|
+
* @example
|
|
3764
|
+
* ```typescript
|
|
3765
|
+
* asyncConditions: {
|
|
3766
|
+
* checkPermission: async (context) => {
|
|
3767
|
+
* const response = await fetch(`/api/permissions?role=${context.formValue.role}`);
|
|
3768
|
+
* const data = await response.json();
|
|
3769
|
+
* return data.canEdit;
|
|
3770
|
+
* },
|
|
3771
|
+
* }
|
|
3772
|
+
* ```
|
|
3773
|
+
*/
|
|
3774
|
+
asyncConditions?: Record<string, AsyncConditionFunction<TFormValue>>;
|
|
2895
3775
|
/**
|
|
2896
3776
|
* Custom validators using Angular's public FieldContext API
|
|
2897
3777
|
*
|
|
@@ -3009,6 +3889,10 @@ interface CustomFnConfig {
|
|
|
3009
3889
|
*/
|
|
3010
3890
|
asyncValidators?: Record<string, AsyncCustomValidator>;
|
|
3011
3891
|
/**
|
|
3892
|
+
* @deprecated Prefer declarative HTTP validators using `type: 'http'` with `http` + `responseMapping`
|
|
3893
|
+
* in the validators array. Function-based HTTP validators now also use `type: 'http'` with `functionName`.
|
|
3894
|
+
* Will be removed in a future minor version.
|
|
3895
|
+
*
|
|
3012
3896
|
* HTTP validators using Angular's validateHttp() API
|
|
3013
3897
|
*
|
|
3014
3898
|
* Angular's validateHttp provides HTTP validation with automatic request
|
|
@@ -3134,22 +4018,49 @@ interface FormOptions {
|
|
|
3134
4018
|
*/
|
|
3135
4019
|
submitButton?: SubmitButtonOptions;
|
|
3136
4020
|
/**
|
|
3137
|
-
* Default disabled behavior for next page buttons.
|
|
4021
|
+
* Default disabled behavior for next page buttons.
|
|
4022
|
+
*
|
|
4023
|
+
* Controls when next page buttons are automatically disabled in paged forms.
|
|
4024
|
+
* Can be overridden per-button via the `logic` array on individual button fields.
|
|
4025
|
+
*
|
|
4026
|
+
* @example
|
|
4027
|
+
* ```typescript
|
|
4028
|
+
* options: {
|
|
4029
|
+
* nextButton: {
|
|
4030
|
+
* disableWhenPageInvalid: true, // Disable when current page is invalid
|
|
4031
|
+
* disableWhileSubmitting: true, // Disable during submission
|
|
4032
|
+
* }
|
|
4033
|
+
* }
|
|
4034
|
+
* ```
|
|
4035
|
+
*/
|
|
4036
|
+
nextButton?: NextButtonOptions;
|
|
4037
|
+
/**
|
|
4038
|
+
* Whether to exclude values of hidden fields from submission output.
|
|
4039
|
+
*
|
|
4040
|
+
* Overrides the global `withValueExclusionDefaults()` setting for this form.
|
|
4041
|
+
* Can be further overridden per-field on individual `FieldDef` entries.
|
|
4042
|
+
*
|
|
4043
|
+
* @default undefined (uses global setting)
|
|
4044
|
+
*/
|
|
4045
|
+
excludeValueIfHidden?: boolean;
|
|
4046
|
+
/**
|
|
4047
|
+
* Whether to exclude values of disabled fields from submission output.
|
|
4048
|
+
*
|
|
4049
|
+
* Overrides the global `withValueExclusionDefaults()` setting for this form.
|
|
4050
|
+
* Can be further overridden per-field on individual `FieldDef` entries.
|
|
4051
|
+
*
|
|
4052
|
+
* @default undefined (uses global setting)
|
|
4053
|
+
*/
|
|
4054
|
+
excludeValueIfDisabled?: boolean;
|
|
4055
|
+
/**
|
|
4056
|
+
* Whether to exclude values of readonly fields from submission output.
|
|
3138
4057
|
*
|
|
3139
|
-
*
|
|
3140
|
-
* Can be overridden per-
|
|
4058
|
+
* Overrides the global `withValueExclusionDefaults()` setting for this form.
|
|
4059
|
+
* Can be further overridden per-field on individual `FieldDef` entries.
|
|
3141
4060
|
*
|
|
3142
|
-
* @
|
|
3143
|
-
* ```typescript
|
|
3144
|
-
* options: {
|
|
3145
|
-
* nextButton: {
|
|
3146
|
-
* disableWhenPageInvalid: true, // Disable when current page is invalid
|
|
3147
|
-
* disableWhileSubmitting: true, // Disable during submission
|
|
3148
|
-
* }
|
|
3149
|
-
* }
|
|
3150
|
-
* ```
|
|
4061
|
+
* @default undefined (uses global setting)
|
|
3151
4062
|
*/
|
|
3152
|
-
|
|
4063
|
+
excludeValueIfReadonly?: boolean;
|
|
3153
4064
|
/**
|
|
3154
4065
|
* Whether to attach the current form value to all events dispatched through the EventBus.
|
|
3155
4066
|
*
|
|
@@ -3430,15 +4341,10 @@ declare class DynamicForm<TFields extends RegisteredFieldTypes[] = RegisteredFie
|
|
|
3430
4341
|
private injector;
|
|
3431
4342
|
private eventBus;
|
|
3432
4343
|
private logger;
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
*
|
|
3436
|
-
|
|
3437
|
-
* in computeds/effects, which are all lazy and evaluated after construction.
|
|
3438
|
-
*/
|
|
3439
|
-
private readonly _connectStateDeps;
|
|
3440
|
-
/** State manager that owns all form state. */
|
|
3441
|
-
private stateManager;
|
|
4344
|
+
private dispatcher;
|
|
4345
|
+
/** State manager that owns all form state. Initialized via connectDeps() to guarantee
|
|
4346
|
+
* FORM_STATE_DEPS is populated before FormStateManager is injected. */
|
|
4347
|
+
private readonly stateManager;
|
|
3442
4348
|
private componentId;
|
|
3443
4349
|
/** The currently active config used for form rendering */
|
|
3444
4350
|
activeConfig: Signal<FormConfig<TFields, InferFormValue$1<TFields extends readonly RegisteredFieldTypes[] ? TFields : RegisteredFieldTypes[]>, Record<string, unknown>, unknown> | undefined>;
|
|
@@ -3454,6 +4360,9 @@ declare class DynamicForm<TFields extends RegisteredFieldTypes[] = RegisteredFie
|
|
|
3454
4360
|
maxDerivationIterations?: number;
|
|
3455
4361
|
submitButton?: _ng_forge_dynamic_forms.SubmitButtonOptions;
|
|
3456
4362
|
nextButton?: _ng_forge_dynamic_forms.NextButtonOptions;
|
|
4363
|
+
excludeValueIfHidden?: boolean;
|
|
4364
|
+
excludeValueIfDisabled?: boolean;
|
|
4365
|
+
excludeValueIfReadonly?: boolean;
|
|
3457
4366
|
emitFormValueOnEvents?: boolean;
|
|
3458
4367
|
}>;
|
|
3459
4368
|
/** Field signal context for injection into child components */
|
|
@@ -3473,7 +4382,7 @@ declare class DynamicForm<TFields extends RegisteredFieldTypes[] = RegisteredFie
|
|
|
3473
4382
|
/** Whether any form field has been touched (blurred) */
|
|
3474
4383
|
touched: Signal<boolean>;
|
|
3475
4384
|
/** Current validation errors from all fields */
|
|
3476
|
-
errors: Signal<_angular_forms_signals.ValidationError.
|
|
4385
|
+
errors: Signal<_angular_forms_signals.ValidationError.WithFieldTree[]>;
|
|
3477
4386
|
/** Whether the form is disabled (from options or form state) */
|
|
3478
4387
|
disabled: Signal<boolean>;
|
|
3479
4388
|
/** Whether the form is currently submitting */
|
|
@@ -3484,6 +4393,13 @@ declare class DynamicForm<TFields extends RegisteredFieldTypes[] = RegisteredFie
|
|
|
3484
4393
|
shouldRender: Signal<boolean>;
|
|
3485
4394
|
/** Resolved fields ready for rendering */
|
|
3486
4395
|
protected resolvedFields: Signal<ResolvedField[]>;
|
|
4396
|
+
/**
|
|
4397
|
+
* Recursively counts container components that will emit ComponentInitializedEvent.
|
|
4398
|
+
* Includes the dynamic-form component itself (+1).
|
|
4399
|
+
*
|
|
4400
|
+
* Recurses into all container children, including those nested inside array
|
|
4401
|
+
* item templates, to avoid a premature (initialized) emission.
|
|
4402
|
+
*/
|
|
3487
4403
|
private totalComponentsCount;
|
|
3488
4404
|
initialized$: rxjs.Observable<boolean>;
|
|
3489
4405
|
/** Emits when form validity changes. */
|
|
@@ -3529,11 +4445,176 @@ declare class DynamicForm<TFields extends RegisteredFieldTypes[] = RegisteredFie
|
|
|
3529
4445
|
*/
|
|
3530
4446
|
protected onNativeSubmit(event: Event): void;
|
|
3531
4447
|
private setupEffects;
|
|
4448
|
+
/**
|
|
4449
|
+
* Populates FORM_STATE_DEPS with this component's input signals, then injects
|
|
4450
|
+
* FormStateManager. Must be called as a field initializer (after the input signals
|
|
4451
|
+
* are declared) so that FormStateManager reads populated deps when it is constructed.
|
|
4452
|
+
* inject() is valid here because field initializers run inside the injection context.
|
|
4453
|
+
*/
|
|
4454
|
+
private connectDeps;
|
|
3532
4455
|
private setupEventHandlers;
|
|
3533
4456
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DynamicForm<any, any>, never>;
|
|
3534
4457
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DynamicForm<any, any>, "form[dynamic-form]", never, { "config": { "alias": "dynamic-form"; "required": true; "isSignal": true; }; "formOptions": { "alias": "formOptions"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "validityChange": "validityChange"; "dirtyChange": "dirtyChange"; "submitted": "submitted"; "reset": "reset"; "cleared": "cleared"; "events": "events"; "initialized": "initialized"; "onPageChange": "onPageChange"; "onPageNavigationStateChange": "onPageNavigationStateChange"; }, never, never, true, never>;
|
|
3535
4458
|
}
|
|
3536
4459
|
|
|
4460
|
+
declare class EventBus {
|
|
4461
|
+
private readonly pipeline$;
|
|
4462
|
+
private readonly globalEmitFormValue;
|
|
4463
|
+
private readonly rootFormRegistry;
|
|
4464
|
+
private readonly formOptions;
|
|
4465
|
+
private readonly logger;
|
|
4466
|
+
events$: Observable<FormEvent>;
|
|
4467
|
+
/**
|
|
4468
|
+
* Dispatches a pre-created event instance directly.
|
|
4469
|
+
*
|
|
4470
|
+
* Use this overload with the `arrayEvent()` factory or any other code that
|
|
4471
|
+
* produces a `FormEvent` instance rather than a constructor:
|
|
4472
|
+
*
|
|
4473
|
+
* ```typescript
|
|
4474
|
+
* eventBus.dispatch(arrayEvent('contacts').append(template));
|
|
4475
|
+
* eventBus.dispatch(arrayEvent('contacts').pop());
|
|
4476
|
+
* ```
|
|
4477
|
+
*
|
|
4478
|
+
* @param event - A FormEvent instance to dispatch
|
|
4479
|
+
*/
|
|
4480
|
+
dispatch(event: FormEvent): void;
|
|
4481
|
+
/**
|
|
4482
|
+
* Dispatches an event to all subscribers by instantiating the provided constructor.
|
|
4483
|
+
*
|
|
4484
|
+
* Creates an instance of the provided event constructor and broadcasts it
|
|
4485
|
+
* through the event pipeline to all active subscribers.
|
|
4486
|
+
*
|
|
4487
|
+
* If `withEventFormValue()` is enabled globally or `options.emitFormValueOnEvents`
|
|
4488
|
+
* is set to `true` in the form config, the current form value will be attached
|
|
4489
|
+
* to the event's `formValue` property.
|
|
4490
|
+
*
|
|
4491
|
+
* @param eventConstructor - Constructor function for the event to dispatch
|
|
4492
|
+
* @param args - Arguments to pass to the event constructor
|
|
4493
|
+
*
|
|
4494
|
+
* @example
|
|
4495
|
+
* ```typescript
|
|
4496
|
+
* // Dispatch a submit event
|
|
4497
|
+
* eventBus.dispatch(SubmitEvent);
|
|
4498
|
+
*
|
|
4499
|
+
* // Dispatch a custom event with args
|
|
4500
|
+
* eventBus.dispatch(CustomFormEvent, 'arg1', 42);
|
|
4501
|
+
* ```
|
|
4502
|
+
*/
|
|
4503
|
+
dispatch<T extends FormEventConstructor>(eventConstructor: T, ...args: ConstructorParameters<T>): void;
|
|
4504
|
+
/**
|
|
4505
|
+
* Dispatches a pre-created event instance directly.
|
|
4506
|
+
* Used internally by EventDispatcher to forward events into the bus.
|
|
4507
|
+
* @internal
|
|
4508
|
+
*/
|
|
4509
|
+
emitInstance(event: FormEvent): void;
|
|
4510
|
+
/**
|
|
4511
|
+
* Shared emit path for both dispatch() and emitInstance().
|
|
4512
|
+
* Attaches form value if configured, then pushes to the pipeline.
|
|
4513
|
+
*/
|
|
4514
|
+
private emit;
|
|
4515
|
+
/**
|
|
4516
|
+
* Emits an event through the pipeline. Catches any synchronous exception that escapes
|
|
4517
|
+
* RxJS's own error handling so dispatch() callers are never disrupted by a failing subscriber.
|
|
4518
|
+
*/
|
|
4519
|
+
private safeEmit;
|
|
4520
|
+
/**
|
|
4521
|
+
* Determines whether form value should be attached to events.
|
|
4522
|
+
*
|
|
4523
|
+
* Precedence rules:
|
|
4524
|
+
* 1. Per-form setting (if defined) takes precedence
|
|
4525
|
+
* 2. Falls back to global setting
|
|
4526
|
+
*/
|
|
4527
|
+
private shouldEmitFormValue;
|
|
4528
|
+
/**
|
|
4529
|
+
* Subscribes to events of a specific type.
|
|
4530
|
+
*
|
|
4531
|
+
* @param eventType - The type of event to subscribe to
|
|
4532
|
+
* @returns Observable that emits events of the specified type
|
|
4533
|
+
*/
|
|
4534
|
+
on<T extends FormEvent>(eventType: T['type']): Observable<T>;
|
|
4535
|
+
/**
|
|
4536
|
+
* Subscribes to events of multiple types.
|
|
4537
|
+
*
|
|
4538
|
+
* @param eventType - Array of event types to subscribe to
|
|
4539
|
+
* @returns Observable that emits events matching any of the specified types
|
|
4540
|
+
*/
|
|
4541
|
+
on<T extends FormEvent>(eventType: Array<T['type']>): Observable<T>;
|
|
4542
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EventBus, never>;
|
|
4543
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<EventBus>;
|
|
4544
|
+
}
|
|
4545
|
+
|
|
4546
|
+
/**
|
|
4547
|
+
* Injectable service for dispatching events into a DynamicForm from outside the form.
|
|
4548
|
+
*
|
|
4549
|
+
* ## When to use
|
|
4550
|
+
*
|
|
4551
|
+
* Use `EventDispatcher` when you need to drive form behaviour **from the host component** —
|
|
4552
|
+
* for example, appending array items in response to a field value change, triggering a form
|
|
4553
|
+
* reset from a toolbar button, or reacting to external application state.
|
|
4554
|
+
*
|
|
4555
|
+
* This is the recommended alternative to accessing the form's internals via `viewChild`.
|
|
4556
|
+
*
|
|
4557
|
+
* ## Setup
|
|
4558
|
+
*
|
|
4559
|
+
* Provide `EventDispatcher` at the **host component** level (not root). DynamicForm
|
|
4560
|
+
* automatically detects it and connects its internal event bus to the dispatcher.
|
|
4561
|
+
*
|
|
4562
|
+
* ```typescript
|
|
4563
|
+
* @Component({
|
|
4564
|
+
* providers: [EventDispatcher],
|
|
4565
|
+
* template: `<form [dynamic-form]="config" [(value)]="formValue"></form>`
|
|
4566
|
+
* })
|
|
4567
|
+
* export class MyComponent {
|
|
4568
|
+
* readonly dispatcher = inject(EventDispatcher);
|
|
4569
|
+
* readonly formValue = signal<Record<string, unknown>>({});
|
|
4570
|
+
*
|
|
4571
|
+
* constructor() {
|
|
4572
|
+
* effect(() => {
|
|
4573
|
+
* const category = this.formValue()?.['category'] as string | undefined;
|
|
4574
|
+
* if (category) {
|
|
4575
|
+
* this.dispatcher.dispatch(
|
|
4576
|
+
* arrayEvent('tasks').append([{ key: 'name', type: 'input', label: 'Task', value: category }])
|
|
4577
|
+
* );
|
|
4578
|
+
* }
|
|
4579
|
+
* });
|
|
4580
|
+
* }
|
|
4581
|
+
* }
|
|
4582
|
+
* ```
|
|
4583
|
+
*
|
|
4584
|
+
* ## Multi-form note
|
|
4585
|
+
*
|
|
4586
|
+
* If multiple `DynamicForm` instances exist under the same provider scope, **all forms**
|
|
4587
|
+
* will receive dispatched events. To target a specific form, scope the provider to a
|
|
4588
|
+
* wrapper component that contains only that form.
|
|
4589
|
+
*
|
|
4590
|
+
* ## What events can be dispatched
|
|
4591
|
+
*
|
|
4592
|
+
* Any `FormEvent` instance is accepted — array events, reset/clear events, custom events, etc.
|
|
4593
|
+
* The `arrayEvent()` builder is the recommended way to construct array manipulation events:
|
|
4594
|
+
*
|
|
4595
|
+
* ```typescript
|
|
4596
|
+
* dispatcher.dispatch(arrayEvent('tasks').append(template));
|
|
4597
|
+
* dispatcher.dispatch(arrayEvent('tasks').removeAt(0));
|
|
4598
|
+
* dispatcher.dispatch(new FormResetEvent());
|
|
4599
|
+
* ```
|
|
4600
|
+
*/
|
|
4601
|
+
declare class EventDispatcher {
|
|
4602
|
+
private bus;
|
|
4603
|
+
/**
|
|
4604
|
+
* Dispatches a form event into the connected DynamicForm's event bus.
|
|
4605
|
+
* No-op if no form is currently connected.
|
|
4606
|
+
*
|
|
4607
|
+
* @param event - A FormEvent instance. Use the `arrayEvent()` builder for array operations.
|
|
4608
|
+
*/
|
|
4609
|
+
dispatch(event: FormEvent): void;
|
|
4610
|
+
/** @internal - Called by DynamicForm on init */
|
|
4611
|
+
connect(bus: EventBus): void;
|
|
4612
|
+
/** @internal - Called by DynamicForm on destroy */
|
|
4613
|
+
disconnect(): void;
|
|
4614
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EventDispatcher, never>;
|
|
4615
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<EventDispatcher>;
|
|
4616
|
+
}
|
|
4617
|
+
|
|
3537
4618
|
/**
|
|
3538
4619
|
* Base interface for dynamic form features.
|
|
3539
4620
|
* Features are configuration options that can be passed to provideDynamicForm
|
|
@@ -3860,6 +4941,100 @@ declare class NoopLogger implements Logger {
|
|
|
3860
4941
|
*/
|
|
3861
4942
|
declare function withEventFormValue(): DynamicFormFeature<'event-form-value'>;
|
|
3862
4943
|
|
|
4944
|
+
/**
|
|
4945
|
+
* Configuration for excluding field values from form submission output
|
|
4946
|
+
* based on their reactive state (hidden, disabled, readonly).
|
|
4947
|
+
*
|
|
4948
|
+
* Supports a 3-tier configuration hierarchy: Field > Form > Global.
|
|
4949
|
+
* The most specific level wins for each property.
|
|
4950
|
+
*
|
|
4951
|
+
* @public
|
|
4952
|
+
*/
|
|
4953
|
+
interface ValueExclusionConfig {
|
|
4954
|
+
/**
|
|
4955
|
+
* Whether to exclude the value of hidden fields from submission output.
|
|
4956
|
+
*
|
|
4957
|
+
* When `true`, fields whose `hidden()` state is `true` will have their
|
|
4958
|
+
* values omitted from the submitted form value.
|
|
4959
|
+
*
|
|
4960
|
+
* @remarks
|
|
4961
|
+
* This does NOT affect HiddenField (`type: 'hidden'`) — those fields
|
|
4962
|
+
* store values without UI and their `hidden()` state is always `false`.
|
|
4963
|
+
*/
|
|
4964
|
+
readonly excludeValueIfHidden?: boolean;
|
|
4965
|
+
/**
|
|
4966
|
+
* Whether to exclude the value of disabled fields from submission output.
|
|
4967
|
+
*
|
|
4968
|
+
* When `true`, fields whose `disabled()` state is `true` will have their
|
|
4969
|
+
* values omitted from the submitted form value.
|
|
4970
|
+
*/
|
|
4971
|
+
readonly excludeValueIfDisabled?: boolean;
|
|
4972
|
+
/**
|
|
4973
|
+
* Whether to exclude the value of readonly fields from submission output.
|
|
4974
|
+
*
|
|
4975
|
+
* When `true`, fields whose `readonly()` state is `true` will have their
|
|
4976
|
+
* values omitted from the submitted form value.
|
|
4977
|
+
*/
|
|
4978
|
+
readonly excludeValueIfReadonly?: boolean;
|
|
4979
|
+
}
|
|
4980
|
+
/**
|
|
4981
|
+
* Fully resolved exclusion config with all properties required.
|
|
4982
|
+
* Produced by the 3-tier resolution: `field ?? form ?? global`.
|
|
4983
|
+
*
|
|
4984
|
+
* @public
|
|
4985
|
+
*/
|
|
4986
|
+
type ResolvedValueExclusionConfig = Required<ValueExclusionConfig>;
|
|
4987
|
+
|
|
4988
|
+
/**
|
|
4989
|
+
* Configures global value exclusion defaults for form submission output.
|
|
4990
|
+
*
|
|
4991
|
+
* Value exclusion is **enabled by default** — field values are excluded from the
|
|
4992
|
+
* `(submitted)` output based on their reactive state. Use this feature to
|
|
4993
|
+
* override those defaults. This does NOT affect two-way binding (`value` model /
|
|
4994
|
+
* `entity`) — fields retain their values internally.
|
|
4995
|
+
*
|
|
4996
|
+
* @example Default behavior (all exclusions enabled)
|
|
4997
|
+
* ```typescript
|
|
4998
|
+
* provideDynamicForm(
|
|
4999
|
+
* ...withMaterialFields(),
|
|
5000
|
+
* withValueExclusionDefaults()
|
|
5001
|
+
* )
|
|
5002
|
+
* ```
|
|
5003
|
+
*
|
|
5004
|
+
* @example Disable specific exclusions
|
|
5005
|
+
* ```typescript
|
|
5006
|
+
* provideDynamicForm(
|
|
5007
|
+
* ...withMaterialFields(),
|
|
5008
|
+
* withValueExclusionDefaults({ excludeValueIfReadonly: false })
|
|
5009
|
+
* )
|
|
5010
|
+
* ```
|
|
5011
|
+
*
|
|
5012
|
+
* @example Disable all exclusions (restore pre-v1 behavior)
|
|
5013
|
+
* ```typescript
|
|
5014
|
+
* provideDynamicForm(
|
|
5015
|
+
* ...withMaterialFields(),
|
|
5016
|
+
* withValueExclusionDefaults({
|
|
5017
|
+
* excludeValueIfHidden: false,
|
|
5018
|
+
* excludeValueIfDisabled: false,
|
|
5019
|
+
* excludeValueIfReadonly: false,
|
|
5020
|
+
* })
|
|
5021
|
+
* )
|
|
5022
|
+
* ```
|
|
5023
|
+
*
|
|
5024
|
+
* @remarks
|
|
5025
|
+
* **Precedence rules:**
|
|
5026
|
+
* 1. Per-field `excludeValueIf*` on `FieldDef` — wins for that field
|
|
5027
|
+
* 2. Per-form `excludeValueIf*` on `FormOptions` — wins for all fields in that form
|
|
5028
|
+
* 3. Global `withValueExclusionDefaults()` — baseline default
|
|
5029
|
+
* 4. No global feature — uses token default (all enabled)
|
|
5030
|
+
*
|
|
5031
|
+
* @param config - Partial override of exclusion rules. Unspecified properties default to `true`.
|
|
5032
|
+
* @returns A DynamicFormFeature that configures value exclusion defaults
|
|
5033
|
+
*
|
|
5034
|
+
* @public
|
|
5035
|
+
*/
|
|
5036
|
+
declare function withValueExclusionDefaults(config?: Partial<ValueExclusionConfig>): DynamicFormFeature<'value-exclusion'>;
|
|
5037
|
+
|
|
3863
5038
|
interface FieldOption<T = unknown> {
|
|
3864
5039
|
label: DynamicText;
|
|
3865
5040
|
value: T;
|
|
@@ -4060,7 +5235,7 @@ interface BaseValueField<TProps, TValue, TMeta extends FieldMeta = FieldMeta> ex
|
|
|
4060
5235
|
required?: boolean;
|
|
4061
5236
|
}
|
|
4062
5237
|
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';
|
|
5238
|
+
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
5239
|
type ValueFieldComponent<T extends BaseValueField<Record<string, unknown> | unknown, unknown>> = Prettify<WithInputSignals<Omit<T, ExcludedKeys$1>>>;
|
|
4065
5240
|
|
|
4066
5241
|
interface BaseCheckedField<TProps, TMeta extends FieldMeta = FieldMeta> extends FieldDef<TProps, TMeta>, FieldWithValidation {
|
|
@@ -4073,7 +5248,7 @@ interface BaseCheckedField<TProps, TMeta extends FieldMeta = FieldMeta> extends
|
|
|
4073
5248
|
required?: boolean;
|
|
4074
5249
|
}
|
|
4075
5250
|
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;
|
|
5251
|
+
type ExcludedKeys = 'type' | 'conditionals' | 'value' | 'disabled' | 'readonly' | 'hidden' | 'col' | keyof FieldWithValidation | 'excludeValueIfHidden' | 'excludeValueIfDisabled' | 'excludeValueIfReadonly';
|
|
4077
5252
|
type CheckedFieldComponent<T extends BaseCheckedField<Record<string, unknown> | unknown>> = Prettify<WithInputSignals<Omit<T, ExcludedKeys>>>;
|
|
4078
5253
|
|
|
4079
5254
|
declare function applyValidator(config: ValidatorConfig, fieldPath: SchemaPath<any> | SchemaPathTree<any>): void;
|
|
@@ -4092,20 +5267,12 @@ declare class PreviousPageEvent implements FormEvent {
|
|
|
4092
5267
|
}
|
|
4093
5268
|
|
|
4094
5269
|
/**
|
|
4095
|
-
* Template type for
|
|
4096
|
-
*
|
|
5270
|
+
* Template type for array items used in events.
|
|
5271
|
+
* Canonical definition lives in {@link ArrayItemDefinition} — this alias
|
|
5272
|
+
* preserves the events-specific naming convention.
|
|
4097
5273
|
*/
|
|
4098
|
-
type
|
|
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: '' }
|
|
4107
|
-
*/
|
|
4108
|
-
type ArrayItemDefinitionTemplate = ArrayAllowedChildren | ArrayItemTemplate;
|
|
5274
|
+
type ArrayItemDefinitionTemplate = ArrayItemDefinition;
|
|
5275
|
+
|
|
4109
5276
|
/**
|
|
4110
5277
|
* Event dispatched to append a new item at the END of an array field.
|
|
4111
5278
|
*
|
|
@@ -4461,92 +5628,6 @@ declare function arrayEvent(arrayKey: string): {
|
|
|
4461
5628
|
removeAt: (index: number) => RemoveAtIndexEvent;
|
|
4462
5629
|
};
|
|
4463
5630
|
|
|
4464
|
-
/**
|
|
4465
|
-
* Event bus service for form-wide event communication.
|
|
4466
|
-
*
|
|
4467
|
-
* Provides type-safe event dispatching and subscription for form components
|
|
4468
|
-
* to communicate without direct coupling. Uses RxJS observables for reactive
|
|
4469
|
-
* event handling and supports both single event type and multiple event type subscriptions.
|
|
4470
|
-
*
|
|
4471
|
-
* @example
|
|
4472
|
-
* ```typescript
|
|
4473
|
-
* @Component({
|
|
4474
|
-
* providers: [EventBus]
|
|
4475
|
-
* })
|
|
4476
|
-
* export class MyFormComponent {
|
|
4477
|
-
* constructor(private eventBus: EventBus) {
|
|
4478
|
-
* // Subscribe to form submission events
|
|
4479
|
-
* this.eventBus.on<SubmitEvent>('submit').subscribe(() => {
|
|
4480
|
-
* console.log('Form was submitted');
|
|
4481
|
-
* });
|
|
4482
|
-
*
|
|
4483
|
-
* // Subscribe to multiple event types
|
|
4484
|
-
* this.eventBus.on<SubmitEvent | FormResetEvent>(['submit', 'form-reset']).subscribe(event => {
|
|
4485
|
-
* console.log('Form event:', event.type);
|
|
4486
|
-
* });
|
|
4487
|
-
* }
|
|
4488
|
-
*
|
|
4489
|
-
* onSubmit() {
|
|
4490
|
-
* // Dispatch a submit event
|
|
4491
|
-
* this.eventBus.dispatch(SubmitEvent);
|
|
4492
|
-
* }
|
|
4493
|
-
* }
|
|
4494
|
-
* ```
|
|
4495
|
-
*/
|
|
4496
|
-
declare class EventBus {
|
|
4497
|
-
private readonly pipeline$;
|
|
4498
|
-
private readonly globalEmitFormValue;
|
|
4499
|
-
private readonly rootFormRegistry;
|
|
4500
|
-
private readonly formOptions;
|
|
4501
|
-
events$: Observable<FormEvent>;
|
|
4502
|
-
/**
|
|
4503
|
-
* Dispatches an event to all subscribers.
|
|
4504
|
-
*
|
|
4505
|
-
* Creates an instance of the provided event constructor and broadcasts it
|
|
4506
|
-
* through the event pipeline to all active subscribers.
|
|
4507
|
-
*
|
|
4508
|
-
* If `withEventFormValue()` is enabled globally or `options.emitFormValueOnEvents`
|
|
4509
|
-
* is set to `true` in the form config, the current form value will be attached
|
|
4510
|
-
* to the event's `formValue` property.
|
|
4511
|
-
*
|
|
4512
|
-
* @param eventConstructor - Constructor function for the event to dispatch
|
|
4513
|
-
*
|
|
4514
|
-
* @example
|
|
4515
|
-
* ```typescript
|
|
4516
|
-
* // Dispatch a submit event
|
|
4517
|
-
* eventBus.dispatch(SubmitEvent);
|
|
4518
|
-
*
|
|
4519
|
-
* // Dispatch a custom event
|
|
4520
|
-
* eventBus.dispatch(CustomFormEvent);
|
|
4521
|
-
* ```
|
|
4522
|
-
*/
|
|
4523
|
-
dispatch<T extends FormEventConstructor>(eventConstructor: T, ...args: ConstructorParameters<T>): void;
|
|
4524
|
-
/**
|
|
4525
|
-
* Determines whether form value should be attached to events.
|
|
4526
|
-
*
|
|
4527
|
-
* Precedence rules:
|
|
4528
|
-
* 1. Per-form setting (if defined) takes precedence
|
|
4529
|
-
* 2. Falls back to global setting
|
|
4530
|
-
*/
|
|
4531
|
-
private shouldEmitFormValue;
|
|
4532
|
-
/**
|
|
4533
|
-
* Subscribes to events of a specific type.
|
|
4534
|
-
*
|
|
4535
|
-
* @param eventType - The type of event to subscribe to
|
|
4536
|
-
* @returns Observable that emits events of the specified type
|
|
4537
|
-
*/
|
|
4538
|
-
on<T extends FormEvent>(eventType: T['type']): Observable<T>;
|
|
4539
|
-
/**
|
|
4540
|
-
* Subscribes to events of multiple types.
|
|
4541
|
-
*
|
|
4542
|
-
* @param eventType - Array of event types to subscribe to
|
|
4543
|
-
* @returns Observable that emits events matching any of the specified types
|
|
4544
|
-
*/
|
|
4545
|
-
on<T extends FormEvent>(eventType: Array<T['type']>): Observable<T>;
|
|
4546
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EventBus, never>;
|
|
4547
|
-
static ɵprov: _angular_core.ɵɵInjectableDeclaration<EventBus>;
|
|
4548
|
-
}
|
|
4549
|
-
|
|
4550
5631
|
/**
|
|
4551
5632
|
* Context for token resolution in event args
|
|
4552
5633
|
*/
|
|
@@ -4759,6 +5840,8 @@ declare function baseFieldMapper(fieldDef: FieldDef<unknown>): Signal<Record<str
|
|
|
4759
5840
|
* Row components are layout containers that don't change the form shape.
|
|
4760
5841
|
* The row component will inject FIELD_SIGNAL_CONTEXT directly.
|
|
4761
5842
|
*
|
|
5843
|
+
* Supports hidden state resolution via `logic` array or static `hidden` property.
|
|
5844
|
+
*
|
|
4762
5845
|
* @param fieldDef The row field definition
|
|
4763
5846
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
4764
5847
|
*/
|
|
@@ -4771,6 +5854,8 @@ declare function rowFieldMapper(fieldDef: RowField): Signal<Record<string, unkno
|
|
|
4771
5854
|
* The group component will inject the parent FIELD_SIGNAL_CONTEXT and create
|
|
4772
5855
|
* a scoped child injector for its nested fields.
|
|
4773
5856
|
*
|
|
5857
|
+
* Supports hidden state resolution via `logic` array or static `hidden` property.
|
|
5858
|
+
*
|
|
4774
5859
|
* @param fieldDef The group field definition
|
|
4775
5860
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
4776
5861
|
*/
|
|
@@ -4783,6 +5868,8 @@ declare function groupFieldMapper(fieldDef: GroupField): Signal<Record<string, u
|
|
|
4783
5868
|
* The array component will inject the parent FIELD_SIGNAL_CONTEXT and create
|
|
4784
5869
|
* a scoped child injector for its array item fields.
|
|
4785
5870
|
*
|
|
5871
|
+
* Supports hidden state resolution via `logic` array or static `hidden` property.
|
|
5872
|
+
*
|
|
4786
5873
|
* @param fieldDef The array field definition
|
|
4787
5874
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
4788
5875
|
*/
|
|
@@ -4794,6 +5881,10 @@ declare function arrayFieldMapper(fieldDef: ArrayField): Signal<Record<string, u
|
|
|
4794
5881
|
* Page fields are layout containers that don't modify the form context.
|
|
4795
5882
|
* The page component will inject FIELD_SIGNAL_CONTEXT directly.
|
|
4796
5883
|
*
|
|
5884
|
+
* Note: Unlike other container mappers (group, row, array), the page mapper does NOT
|
|
5885
|
+
* resolve hidden logic here. Page visibility is managed by the {@link PageOrchestratorComponent}
|
|
5886
|
+
* which evaluates `ContainerLogicConfig` conditions and controls the `isVisible` input.
|
|
5887
|
+
*
|
|
4797
5888
|
* @param fieldDef The page field definition
|
|
4798
5889
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
4799
5890
|
*/
|
|
@@ -4906,6 +5997,7 @@ declare class RowFieldComponent {
|
|
|
4906
5997
|
field: _angular_core.InputSignal<RowField<readonly _ng_forge_dynamic_forms.RowAllowedChildren[]>>;
|
|
4907
5998
|
key: _angular_core.InputSignal<string>;
|
|
4908
5999
|
className: _angular_core.InputSignal<string | undefined>;
|
|
6000
|
+
hidden: _angular_core.InputSignal<boolean>;
|
|
4909
6001
|
readonly hostClasses: _angular_core.Signal<string>;
|
|
4910
6002
|
readonly disabled: _angular_core.Signal<boolean>;
|
|
4911
6003
|
private readonly rawFieldRegistry;
|
|
@@ -4914,7 +6006,7 @@ declare class RowFieldComponent {
|
|
|
4914
6006
|
constructor();
|
|
4915
6007
|
private setupEffects;
|
|
4916
6008
|
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>;
|
|
6009
|
+
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
6010
|
}
|
|
4919
6011
|
|
|
4920
6012
|
/**
|
|
@@ -4935,6 +6027,7 @@ declare class GroupFieldComponent<TModel extends Record<string, unknown> = Recor
|
|
|
4935
6027
|
field: _angular_core.InputSignal<GroupField<readonly _ng_forge_dynamic_forms.GroupAllowedChildren[]>>;
|
|
4936
6028
|
key: _angular_core.InputSignal<string>;
|
|
4937
6029
|
className: _angular_core.InputSignal<string | undefined>;
|
|
6030
|
+
hidden: _angular_core.InputSignal<boolean>;
|
|
4938
6031
|
readonly hostClasses: _angular_core.Signal<string>;
|
|
4939
6032
|
private readonly rawFieldRegistry;
|
|
4940
6033
|
private readonly formSetup;
|
|
@@ -4951,7 +6044,7 @@ declare class GroupFieldComponent<TModel extends Record<string, unknown> = Recor
|
|
|
4951
6044
|
readonly invalid: _angular_core.Signal<boolean>;
|
|
4952
6045
|
readonly dirty: _angular_core.Signal<boolean>;
|
|
4953
6046
|
readonly touched: _angular_core.Signal<boolean>;
|
|
4954
|
-
readonly errors: _angular_core.Signal<_angular_forms_signals.ValidationError.
|
|
6047
|
+
readonly errors: _angular_core.Signal<_angular_forms_signals.ValidationError.WithFieldTree[]>;
|
|
4955
6048
|
readonly disabled: _angular_core.Signal<boolean>;
|
|
4956
6049
|
private readonly nestedFieldTree;
|
|
4957
6050
|
private readonly groupFieldSignalContext;
|
|
@@ -4964,7 +6057,7 @@ declare class GroupFieldComponent<TModel extends Record<string, unknown> = Recor
|
|
|
4964
6057
|
constructor();
|
|
4965
6058
|
private setupEffects;
|
|
4966
6059
|
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>;
|
|
6060
|
+
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
6061
|
}
|
|
4969
6062
|
|
|
4970
6063
|
/**
|
|
@@ -5011,14 +6104,40 @@ declare class ArrayFieldComponent<TModel extends Record<string, unknown> = Recor
|
|
|
5011
6104
|
field: _angular_core.InputSignal<ArrayField<readonly ArrayItemDefinition[]>>;
|
|
5012
6105
|
key: _angular_core.InputSignal<string>;
|
|
5013
6106
|
className: _angular_core.InputSignal<string | undefined>;
|
|
5014
|
-
|
|
6107
|
+
hidden: _angular_core.InputSignal<boolean>;
|
|
6108
|
+
readonly hostClasses: Signal<string>;
|
|
5015
6109
|
private readonly rawFieldRegistry;
|
|
6110
|
+
/**
|
|
6111
|
+
* Gets the auto-remove button FieldDef from normalization metadata.
|
|
6112
|
+
* Set by simplified array normalization for primitive arrays with remove buttons.
|
|
6113
|
+
* The button is rendered alongside each item without wrapping in a row,
|
|
6114
|
+
* preserving flat primitive form values.
|
|
6115
|
+
*/
|
|
6116
|
+
private readonly autoRemoveButton;
|
|
6117
|
+
/**
|
|
6118
|
+
* For primitive array items, the key of the value field template (e.g., 'value').
|
|
6119
|
+
* Used to wrap the FormControl in the item context so getFieldTree(key) works.
|
|
6120
|
+
* Returns undefined for object arrays (FormGroup items have natural child navigation).
|
|
6121
|
+
*
|
|
6122
|
+
* Detection order:
|
|
6123
|
+
* 1. Normalization metadata (for simplified arrays — always available at normalization time)
|
|
6124
|
+
* 2. Existing item definitions (non-empty full-API arrays)
|
|
6125
|
+
* 3. Dynamically discovered key from handleAddFromEvent (empty full-API arrays)
|
|
6126
|
+
*
|
|
6127
|
+
* Uses linkedSignal: recomputes when field() changes, supports manual set()
|
|
6128
|
+
* for the dynamic discovery case.
|
|
6129
|
+
*/
|
|
6130
|
+
private readonly primitiveFieldKey;
|
|
5016
6131
|
/**
|
|
5017
6132
|
* Gets the item templates (field definitions) for the array.
|
|
5018
6133
|
* Each element can be either:
|
|
5019
6134
|
* - A single FieldDef (primitive item) - normalized to [FieldDef]
|
|
5020
6135
|
* - An array of FieldDefs (object item) - used as-is
|
|
5021
6136
|
*
|
|
6137
|
+
* When auto-remove is configured, the remove button is appended to each item's
|
|
6138
|
+
* template list for rendering. This is purely visual — the form schema uses the
|
|
6139
|
+
* original primitive item definition (single FieldDef → FormControl → flat value).
|
|
6140
|
+
*
|
|
5022
6141
|
* Returns normalized templates where all items are arrays for consistent handling.
|
|
5023
6142
|
*/
|
|
5024
6143
|
private readonly itemTemplates;
|
|
@@ -5031,7 +6150,20 @@ declare class ArrayFieldComponent<TModel extends Record<string, unknown> = Recor
|
|
|
5031
6150
|
*/
|
|
5032
6151
|
private readonly itemPositionMap;
|
|
5033
6152
|
/** Read-only view of resolved items for template consumption. */
|
|
5034
|
-
readonly resolvedItems:
|
|
6153
|
+
readonly resolvedItems: Signal<ResolvedArrayItem[]>;
|
|
6154
|
+
/**
|
|
6155
|
+
* Whether the array has reached its configured maxLength.
|
|
6156
|
+
* Exposed as a public signal so add-button components can bind [disabled]="atMaxLength()".
|
|
6157
|
+
*/
|
|
6158
|
+
readonly atMaxLength: Signal<boolean>;
|
|
6159
|
+
/**
|
|
6160
|
+
* Caches the result of appending the auto-remove button to template arrays.
|
|
6161
|
+
* Keyed by template array reference — cache hits occur during recreate/resolution
|
|
6162
|
+
* operations where stored template references are reused. Add operations via
|
|
6163
|
+
* handleAddFromEvent always create a fresh `[...template]` copy (line ~277),
|
|
6164
|
+
* so each add is a cache miss by design (the spread is needed for mutability).
|
|
6165
|
+
*/
|
|
6166
|
+
private readonly autoRemoveCache;
|
|
5035
6167
|
constructor();
|
|
5036
6168
|
private setupEffects;
|
|
5037
6169
|
private setupEventHandlers;
|
|
@@ -5056,6 +6188,18 @@ declare class ArrayFieldComponent<TModel extends Record<string, unknown> = Recor
|
|
|
5056
6188
|
* 3. Return undefined (item cannot be resolved without a template)
|
|
5057
6189
|
*/
|
|
5058
6190
|
private createResolveItemObservable;
|
|
6191
|
+
/**
|
|
6192
|
+
* Appends the auto-remove button to a templates array for rendering.
|
|
6193
|
+
* The button is added for visual rendering only — it doesn't affect the form schema.
|
|
6194
|
+
* Original templates are stored in templateRegistry WITHOUT the remove button,
|
|
6195
|
+
* so this method is called during resolution to add it dynamically.
|
|
6196
|
+
*
|
|
6197
|
+
* Uses a WeakMap cache keyed by template array reference. Cache hits occur
|
|
6198
|
+
* during recreate/resolution paths where stored templates are reused.
|
|
6199
|
+
* Add operations always pass a fresh `[...template]` copy, so they miss
|
|
6200
|
+
* the cache intentionally (the copy is needed for mutable item construction).
|
|
6201
|
+
*/
|
|
6202
|
+
private withAutoRemove;
|
|
5059
6203
|
/**
|
|
5060
6204
|
* Handles remove operations from events (pop, shift, removeAt).
|
|
5061
6205
|
* Updates resolvedItems FIRST, then form value - this ensures differential
|
|
@@ -5064,7 +6208,7 @@ declare class ArrayFieldComponent<TModel extends Record<string, unknown> = Recor
|
|
|
5064
6208
|
*/
|
|
5065
6209
|
private removeItem;
|
|
5066
6210
|
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>;
|
|
6211
|
+
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
6212
|
}
|
|
5069
6213
|
|
|
5070
6214
|
/**
|
|
@@ -5150,5 +6294,12 @@ declare class RootFormRegistryService {
|
|
|
5150
6294
|
constructor(formValue: Signal<Record<string, unknown>>, rootForm: Signal<FieldTree<Record<string, unknown>> | undefined>);
|
|
5151
6295
|
}
|
|
5152
6296
|
|
|
5153
|
-
|
|
5154
|
-
|
|
6297
|
+
/**
|
|
6298
|
+
* Injection token for configuring the initialization timeout in milliseconds.
|
|
6299
|
+
* Defaults to 10 seconds. When the timeout is reached, a warning is logged
|
|
6300
|
+
* and (initialized) emits true as a best-effort fallback.
|
|
6301
|
+
*/
|
|
6302
|
+
declare const INITIALIZATION_TIMEOUT_MS: InjectionToken<number>;
|
|
6303
|
+
|
|
6304
|
+
export { ARRAY_CONTEXT, AppendArrayItemEvent, ArrayFieldComponent, BUILT_IN_FIELDS, ConsoleLogger, DEFAULT_PROPS, DEFAULT_VALIDATION_MESSAGES, DynamicForm, DynamicFormError, DynamicFormLogger, DynamicTextPipe, EventBus, EventDispatcher, FIELD_REGISTRY, FIELD_SIGNAL_CONTEXT, FORM_OPTIONS, FormClearEvent, FormResetEvent, GroupFieldComponent, INITIALIZATION_TIMEOUT_MS, 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 };
|
|
6305
|
+
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 };
|