@ng-forge/dynamic-forms 1.3.0-next.3 → 1.3.0-next.4

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.
Files changed (21) hide show
  1. package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-bnrwNw7Y.mjs +156 -0
  2. package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-bnrwNw7Y.mjs.map +1 -0
  3. package/fesm2022/{ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-EuYCbquo.mjs → ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-B6WH0Etk.mjs} +2 -2
  4. package/fesm2022/{ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-EuYCbquo.mjs.map → ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-B6WH0Etk.mjs.map} +1 -1
  5. package/fesm2022/{ng-forge-dynamic-forms-bootstrap-web-mcp-2wQK_wPp.mjs → ng-forge-dynamic-forms-bootstrap-web-mcp-VjJn-JeD.mjs} +2 -2
  6. package/fesm2022/{ng-forge-dynamic-forms-bootstrap-web-mcp-2wQK_wPp.mjs.map → ng-forge-dynamic-forms-bootstrap-web-mcp-VjJn-JeD.mjs.map} +1 -1
  7. package/fesm2022/{ng-forge-dynamic-forms-form-state-manager-DcOXRFRL.mjs → ng-forge-dynamic-forms-form-state-manager-BJKBX4FL.mjs} +26 -3
  8. package/fesm2022/ng-forge-dynamic-forms-form-state-manager-BJKBX4FL.mjs.map +1 -0
  9. package/fesm2022/ng-forge-dynamic-forms-internal.mjs +109 -14
  10. package/fesm2022/ng-forge-dynamic-forms-internal.mjs.map +1 -1
  11. package/fesm2022/{ng-forge-dynamic-forms-page-field.component-BRjQmWC9.mjs → ng-forge-dynamic-forms-page-field.component-Bsd8YpzL.mjs} +37 -5
  12. package/fesm2022/ng-forge-dynamic-forms-page-field.component-Bsd8YpzL.mjs.map +1 -0
  13. package/fesm2022/ng-forge-dynamic-forms.mjs +85 -26
  14. package/fesm2022/ng-forge-dynamic-forms.mjs.map +1 -1
  15. package/package.json +1 -1
  16. package/types/ng-forge-dynamic-forms-internal.d.ts +9 -0
  17. package/types/ng-forge-dynamic-forms.d.ts +63 -2
  18. package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-CiKN-mcc.mjs +0 -12
  19. package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-CiKN-mcc.mjs.map +0 -1
  20. package/fesm2022/ng-forge-dynamic-forms-form-state-manager-DcOXRFRL.mjs.map +0 -1
  21. package/fesm2022/ng-forge-dynamic-forms-page-field.component-BRjQmWC9.mjs.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-forge/dynamic-forms",
3
- "version": "1.3.0-next.3",
3
+ "version": "1.3.0-next.4",
4
4
  "description": "Type-safe, signal-powered dynamic forms for Angular. Build complex forms from configuration with full TypeScript inference.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -2672,6 +2672,7 @@ export declare enum TokenType {
2672
2672
  LESS_EQUAL = "LESS_EQUAL",
2673
2673
  AND = "AND",
2674
2674
  OR = "OR",
2675
+ NULLISH = "NULLISH",
2675
2676
  NOT = "NOT",
2676
2677
  DOT = "DOT",
2677
2678
  COMMA = "COMMA",
@@ -2785,6 +2786,14 @@ export declare class ExpressionParser {
2785
2786
  maxSize: number;
2786
2787
  };
2787
2788
  }
2789
+ /** Variables a condition expression can read (the keys of `EvaluationContext`). */
2790
+ export declare const CONDITION_SCOPE_VARIABLES: ReadonlySet<string>;
2791
+ /**
2792
+ * Finds constructs that parse but can never work at runtime: a direct function call
2793
+ * (`String(x)`), a method outside the allow-list, or a name that isn't in scope (`Math`),
2794
+ * which reads as `undefined` and makes the expression quietly wrong.
2795
+ */
2796
+ export declare function findStaticExpressionProblems(ast: ASTNode, scope: ReadonlySet<string>): string[];
2788
2797
  /** TTL cache for HTTP condition responses with max entries eviction. */
2789
2798
  export declare class HttpConditionCache {
2790
2799
  private readonly cache;
@@ -106,6 +106,58 @@ export declare class ActivePageInitializedEvent implements FormEvent$1 {
106
106
  readonly type: "active-page-initialized";
107
107
  constructor(pageIndex: number, pageKey: string);
108
108
  }
109
+ /**
110
+ * Field metadata handed to a projected placeholder template as its context —
111
+ * both `$implicit` (for `let-field`) and the named `field`. Deliberately narrow
112
+ * and stable: it is NOT the internal `ResolvedField`.
113
+ */
114
+ interface FieldPlaceholderInfo {
115
+ /** The field's key. */
116
+ readonly key: string;
117
+ /** The field's type (e.g. `input`, `textarea`, `select`). */
118
+ readonly type: string;
119
+ /** The field's label when it is a plain string; translated (Observable or Signal) labels are not resolved. */
120
+ readonly label?: string;
121
+ /** The field's grid column span, if any. */
122
+ readonly col?: number;
123
+ }
124
+ /** Template context for a projected `dfPlaceholder`. */
125
+ interface FieldPlaceholderContext {
126
+ readonly $implicit: FieldPlaceholderInfo;
127
+ readonly field: FieldPlaceholderInfo;
128
+ }
129
+ /**
130
+ * Marks an `<ng-template>` projected into `<form dynamic-form>` content as a
131
+ * field-windowing placeholder. Mirrors {@link DfTemplate}: the template is
132
+ * captured by `DynamicForm` via `contentChildren` and published through
133
+ * {@link DF_FIELD_PLACEHOLDERS} so dynamically-rendered pages can resolve it.
134
+ *
135
+ * - `<ng-template dfPlaceholder let-field>` — default, used for any field
136
+ * - `<ng-template dfPlaceholder="textarea">` — matched by field type
137
+ * - `<ng-template dfPlaceholderKey="username">` — matched by a specific field key
138
+ */
139
+ export declare class DfPlaceholder {
140
+ /** Field-type match, or empty for the default placeholder. */
141
+ readonly dfPlaceholder: import("@angular/core").InputSignal<string>;
142
+ /** Field-key match (escape hatch); wins over a type match. */
143
+ readonly dfPlaceholderKey: import("@angular/core").InputSignal<string>;
144
+ readonly templateRef: TemplateRef<FieldPlaceholderContext>;
145
+ /** Types `let-field` in `<ng-template dfPlaceholder let-field>`. */
146
+ static ngTemplateContextGuard(_dir: DfPlaceholder, ctx: unknown): ctx is FieldPlaceholderContext;
147
+ static ɵfac: i0.ɵɵFactoryDeclaration<DfPlaceholder, never>;
148
+ static ɵdir: i0.ɵɵDirectiveDeclaration<DfPlaceholder, "ng-template[dfPlaceholder], ng-template[dfPlaceholderKey]", ["dfPlaceholder"], {
149
+ "dfPlaceholder": {
150
+ "alias": "dfPlaceholder";
151
+ "required": false;
152
+ "isSignal": true;
153
+ };
154
+ "dfPlaceholderKey": {
155
+ "alias": "dfPlaceholderKey";
156
+ "required": false;
157
+ "isSignal": true;
158
+ };
159
+ }, {}, never, never, true, never>;
160
+ }
109
161
  /** Resolved field ready for rendering with ngComponentOutlet / DfFieldOutlet. */
110
162
  interface ResolvedField {
111
163
  key: string;
@@ -176,9 +228,14 @@ export declare class DynamicForm<TFields extends RegisteredFieldTypes$1[] = Regi
176
228
  private logger;
177
229
  private dispatcher;
178
230
  private templateRegistry;
231
+ private placeholderRegistry;
232
+ private fieldPlaceholders;
179
233
  private globalFieldWindowing;
180
234
  /** All `<ng-template dfTemplate="...">` instances projected into this form. */
181
235
  private readonly _projectedTemplates;
236
+ /** All `<ng-template dfPlaceholder>` instances projected into this form. */
237
+ private readonly _projectedPlaceholders;
238
+ private readonly placeholderContextFor;
182
239
  private readonly stateManager;
183
240
  /**
184
241
  * Owns this form's DOM-id prefix and registers the instance with the root
@@ -324,6 +381,10 @@ export declare class DynamicForm<TFields extends RegisteredFieldTypes$1[] = Regi
324
381
  protected windowsField(field: ResolvedField, index: number): boolean;
325
382
  /** Class string for a windowed field's placeholder — matches the real field's grid column. */
326
383
  protected placeholderGridClass(field: ResolvedField): string;
384
+ /** Projected placeholder template for a windowed field, or null for the built-in bare div. */
385
+ protected placeholderTemplate(field: ResolvedField): TemplateRef<FieldPlaceholderContext> | null;
386
+ /** Memoised template context for a windowed field's projected placeholder. */
387
+ protected placeholderContext(field: ResolvedField): FieldPlaceholderContext;
327
388
  private setupEffects;
328
389
  /**
329
390
  * Populates FORM_STATE_DEPS with this component's input signals, then injects
@@ -367,7 +428,7 @@ export declare class DynamicForm<TFields extends RegisteredFieldTypes$1[] = Regi
367
428
  "activePageInitialized": "activePageInitialized";
368
429
  "onPageChange": "onPageChange";
369
430
  "onPageNavigationStateChange": "onPageNavigationStateChange";
370
- }, ["_projectedTemplates"], never, true, never>;
431
+ }, ["_projectedTemplates", "_projectedPlaceholders"], never, true, never>;
371
432
  }
372
433
  /**
373
434
  * Injectable service for dispatching events into a DynamicForm from outside the form.
@@ -1246,4 +1307,4 @@ interface ArrayItemContext {
1246
1307
  /** Form value for token resolution */
1247
1308
  formValue?: unknown;
1248
1309
  }
1249
- export { type AddonActionContext, type AddonActionPreset, type AddonActionsFeature, type AddonSlot, type AddonTypeDefinition, type AddonWarning, type AnyAddon, type ArrayAllowedChildren, type ArrayButtonConfig, type ArrayField, type ArrayItemContext, type ArrayItemDefinitionTemplate, type ArrayItemTemplate, type AsyncCondition, type AsyncConditionFunction, type AsyncCustomValidator, type AsyncDerivationFunction, type AsyncValidatorConfig, type AvailableFieldTypes, type BaseAddon, type BaseCheckedField, type BaseValidatorConfig, type BaseValueField, type BuiltInValidatorConfig, type CheckedFieldComponent, type CommonAddonActionPreset, type CommonAddonSlot, type ComponentAddon, type ConditionalExpression, type ContainerAllowedChildren, type ContainerField, type ContainerFieldTypes, type CssWrapper, type CustomFnConfig, type CustomFunction, type CustomValidator, type CustomValidatorConfig, DF_FIELD_TEMPLATES, type DeclarativeHttpValidatorConfig, type DynamicFormActionRegistry, type DynamicFormAddonActionPresetRegistry, type DynamicFormAddonRegistry, type DynamicFormAddonSlotRegistry, DynamicFormError, type DynamicFormFieldRegistry, DynamicFormLogger, type DynamicText, type DynamicValue, type EvaluationContext, type ExtractField, type ExtractFieldDefs, type ExtractFormValue, type FieldBoundAddonActionContext, type FieldComponent, type FieldDef, type FieldMeta, type FieldOption, type FieldParkingOption, type FieldPathAccess, type FieldRegistryContainers, type FieldRegistryLeaves, type FieldRegistryWrappers, type FieldWithValidation, type FieldWrapper, type FormConfig, type FormEvent, type FormEventConstructor, type FormMode, type FormModeDetectionResult, type FormOptions, type FormStateCondition, type GroupAllowedChildren, type GroupField, type HiddenField, type HiddenScalar, type HiddenValue, type HttpCondition, type HttpCustomValidator, type HttpRequestConfig, type HttpValidationResponseMapping, type InferFormValue, type InferWrapperRegistry, type InitialPageConfig, type LeafFieldTypes, type Logger, type LogicConfig, type NarrowField, type NarrowFields, type NextButtonOptions, NoopLogger, type OrphanAddonActionContext, type PageAllowedChildren, type PageField, type PageNavigationOptions, type PagerState, type RegisteredActionRef, type RegisteredFieldTypes, type ResolvedValidationExecutionConfig, type ResolvedValueExclusionConfig, type RowAllowedChildren, type RowErrorSpec, type RowField, type SanitizeFormConfigOptions, type SanitizedFormConfig, type SchemaApplicationConfig, type SchemaDefinition, type SimplifiedArrayField, type StateLogicConfig, type SubmissionActionResult, type SubmissionConfig, type SubmissionOutcome, type SubmissionReply, type SubmitButtonOptions, type TemplateAddon, type TextAddon, type TextElementType, type TextField, type TextProps, type TokenContext, type ValidationError, type ValidationExecutionConfig, type ValidationMessage, type ValidationMessageResolver, type ValidationMessages, type ValidatorConfig, type ValueExclusionConfig, type ValueFieldComponent, type ValueType, type WebMcpStatus, type WebMcpToolOptions, type WithInputSignals, type WrapperConfig, type WrapperRegistration, type WrapperTypeDefinition, type WrappersBundle, hasFormValue, isArrayField, isContainerField, isDisplayOnlyField, isFieldBoundContext, isFormStateCondition, isGroupField, isHiddenField, isLeafField, isPageField, isRowField, isSimplifiedArrayField, isValueBearingField, isWrapperTypeDefinition, resolveDynamicValue, rowError };
1310
+ export { type AddonActionContext, type AddonActionPreset, type AddonActionsFeature, type AddonSlot, type AddonTypeDefinition, type AddonWarning, type AnyAddon, type ArrayAllowedChildren, type ArrayButtonConfig, type ArrayField, type ArrayItemContext, type ArrayItemDefinitionTemplate, type ArrayItemTemplate, type AsyncCondition, type AsyncConditionFunction, type AsyncCustomValidator, type AsyncDerivationFunction, type AsyncValidatorConfig, type AvailableFieldTypes, type BaseAddon, type BaseCheckedField, type BaseValidatorConfig, type BaseValueField, type BuiltInValidatorConfig, type CheckedFieldComponent, type CommonAddonActionPreset, type CommonAddonSlot, type ComponentAddon, type ConditionalExpression, type ContainerAllowedChildren, type ContainerField, type ContainerFieldTypes, type CssWrapper, type CustomFnConfig, type CustomFunction, type CustomValidator, type CustomValidatorConfig, DF_FIELD_TEMPLATES, type DeclarativeHttpValidatorConfig, type DynamicFormActionRegistry, type DynamicFormAddonActionPresetRegistry, type DynamicFormAddonRegistry, type DynamicFormAddonSlotRegistry, DynamicFormError, type DynamicFormFieldRegistry, DynamicFormLogger, type DynamicText, type DynamicValue, type EvaluationContext, type ExtractField, type ExtractFieldDefs, type ExtractFormValue, type FieldBoundAddonActionContext, type FieldComponent, type FieldDef, type FieldMeta, type FieldOption, type FieldParkingOption, type FieldPathAccess, type FieldPlaceholderContext, type FieldPlaceholderInfo, type FieldRegistryContainers, type FieldRegistryLeaves, type FieldRegistryWrappers, type FieldWithValidation, type FieldWrapper, type FormConfig, type FormEvent, type FormEventConstructor, type FormMode, type FormModeDetectionResult, type FormOptions, type FormStateCondition, type GroupAllowedChildren, type GroupField, type HiddenField, type HiddenScalar, type HiddenValue, type HttpCondition, type HttpCustomValidator, type HttpRequestConfig, type HttpValidationResponseMapping, type InferFormValue, type InferWrapperRegistry, type InitialPageConfig, type LeafFieldTypes, type Logger, type LogicConfig, type NarrowField, type NarrowFields, type NextButtonOptions, NoopLogger, type OrphanAddonActionContext, type PageAllowedChildren, type PageField, type PageNavigationOptions, type PagerState, type RegisteredActionRef, type RegisteredFieldTypes, type ResolvedValidationExecutionConfig, type ResolvedValueExclusionConfig, type RowAllowedChildren, type RowErrorSpec, type RowField, type SanitizeFormConfigOptions, type SanitizedFormConfig, type SchemaApplicationConfig, type SchemaDefinition, type SimplifiedArrayField, type StateLogicConfig, type SubmissionActionResult, type SubmissionConfig, type SubmissionOutcome, type SubmissionReply, type SubmitButtonOptions, type TemplateAddon, type TextAddon, type TextElementType, type TextField, type TextProps, type TokenContext, type ValidationError, type ValidationExecutionConfig, type ValidationMessage, type ValidationMessageResolver, type ValidationMessages, type ValidatorConfig, type ValueExclusionConfig, type ValueFieldComponent, type ValueType, type WebMcpStatus, type WebMcpToolOptions, type WithInputSignals, type WrapperConfig, type WrapperRegistration, type WrapperTypeDefinition, type WrappersBundle, hasFormValue, isArrayField, isContainerField, isDisplayOnlyField, isFieldBoundContext, isFormStateCondition, isGroupField, isHiddenField, isLeafField, isPageField, isRowField, isSimplifiedArrayField, isValueBearingField, isWrapperTypeDefinition, resolveDynamicValue, rowError };
@@ -1,12 +0,0 @@
1
- var ActivePageInitializedEvent = class {
2
- pageIndex;
3
- pageKey;
4
- type = "active-page-initialized";
5
- constructor(pageIndex, pageKey) {
6
- this.pageIndex = pageIndex;
7
- this.pageKey = pageKey;
8
- }
9
- };
10
- export { ActivePageInitializedEvent as t };
11
-
12
- //# sourceMappingURL=ng-forge-dynamic-forms-active-page-initialized.event-CiKN-mcc.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-active-page-initialized.event-CiKN-mcc.mjs","names":[],"sources":["../../../../packages/dynamic-forms/src/lib/events/constants/active-page-initialized.event.ts"],"sourcesContent":["import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Emitted after the active page and all of its visible fields have rendered. */\nexport class ActivePageInitializedEvent implements FormEvent {\n readonly type = 'active-page-initialized' as const;\n\n constructor(\n public readonly pageIndex: number,\n public readonly pageKey: string,\n ) {}\n}\n"],"mappings":"AAGA,IAAa,6BAAb,MAAuC;CAInB;CACA;CAJT,OAAO;CAEhB,YACkB,WACA,SAAe;EADf,KAAA,YAAA;EACA,KAAA,UAAA;CACf;AACJ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-form-state-manager-DcOXRFRL.mjs","names":["nestedTree"],"sources":["../../../../packages/dynamic-forms/src/lib/events/constants/submit.event.ts","../../../../packages/dynamic-forms/src/lib/utils/array-field/normalize-simplified-arrays.ts","../../../../packages/dynamic-forms/src/lib/utils/form-validation/form-mode-validator.ts","../../../../packages/dynamic-forms/src/lib/utils/config-validation/config-validator.ts","../../../../packages/dynamic-forms/src/lib/utils/validate-form-config/validate-field-addons.ts","../../../../packages/dynamic-forms/src/lib/utils/validate-form-config/addon-warning.ts","../../../../packages/dynamic-forms/src/lib/providers/features/value-exclusion/value-exclusion.token.ts","../../../../packages/dynamic-forms/src/lib/utils/value-filter/value-filter.ts","../../../../packages/dynamic-forms/src/lib/state/state-types.ts","../../../../packages/dynamic-forms/src/lib/state/side-effect-scheduler.ts","../../../../packages/dynamic-forms/src/lib/state/form-state-machine.ts","../../../../packages/dynamic-forms/src/lib/state/form-state-manager.ts"],"sourcesContent":["import { FormEvent } from '@ng-forge/dynamic-forms/internal';\nimport type { SubmissionReply } from '../../utils/submission-handler/submission-outcome';\n\n/**\n * Event dispatched to submit the form (the action behind a `submit` button).\n *\n * A caller that needs to know how the submission ended passes a\n * {@link SubmissionReply}; the submission handler reports back through it. A\n * button click passes nothing and stays fire-and-forget, as before.\n */\nexport class FormSubmitEvent implements FormEvent {\n readonly type = 'submit' as const;\n\n constructor(readonly reply?: SubmissionReply) {}\n}\n","import { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport {\n isSimplifiedArrayField,\n SimplifiedArrayField,\n ArrayButtonConfig,\n ArrayField,\n isArrayField,\n} from '@ng-forge/dynamic-forms/internal';\nimport { isContainerField, hasChildFields } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayAllowedChildren } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayItemDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { setNormalizedArrayMetadata } from './normalized-array-metadata';\nimport { DynamicFormError } from '@ng-forge/dynamic-forms/internal';\n\n/** Normalizes simplified array fields into full array field definitions. */\nexport function normalizeSimplifiedArrays(fields: FieldDef<unknown>[]): FieldDef<unknown>[] {\n return fields.flatMap((field): FieldDef<unknown>[] => {\n // Recurse into non-array containers (page, group, row) that have child fields\n if (isContainerField(field) && !isArrayField(field) && hasChildFields(field)) {\n return [{ ...field, fields: normalizeSimplifiedArrays(field.fields as FieldDef<unknown>[]) } as FieldDef<unknown>];\n }\n\n // Full-API arrays may have simplified arrays nested inside their item templates\n if (isArrayField(field) && !isSimplifiedArrayField(field)) {\n const normalizedItems = field.fields.map((item: ArrayItemDefinition) =>\n Array.isArray(item) ? normalizeSimplifiedArrays(item as FieldDef<unknown>[]) : item,\n );\n return [{ ...field, fields: normalizedItems } as ArrayField as FieldDef<unknown>];\n }\n\n // Expand simplified array fields\n if (isSimplifiedArrayField(field)) {\n const { arrayField, addButton } = expandSimplifiedArray(field);\n return addButton ? [arrayField, addButton] : [arrayField];\n }\n\n // Pass through all other fields unchanged\n return [field];\n });\n}\n\ninterface ExpandedArray {\n arrayField: FieldDef<unknown>;\n addButton?: FieldDef<unknown>;\n}\n\n/**\n * Invalid field types that are not allowed as array children.\n * TypeScript enforces this via ArrayAllowedChildren at compile time,\n * but runtime validation is needed for JavaScript users and dynamic configs.\n */\nconst INVALID_ARRAY_CHILD_TYPES = new Set(['page', 'array']);\n\n/**\n * Validates a simplified array field's template configuration.\n * Throws DynamicFormError for invalid configurations that would silently produce broken output.\n */\nfunction validateSimplifiedTemplate(field: SimplifiedArrayField): void {\n const { template, key } = field;\n const isObjectTemplate = Array.isArray(template);\n\n if (isObjectTemplate) {\n const templateFields = template as readonly ArrayAllowedChildren[];\n for (const tmpl of templateFields) {\n // Cast to FieldDef for runtime check — TypeScript prevents this statically,\n // but dynamic configs (e.g., from JSON) may violate the constraint.\n if (INVALID_ARRAY_CHILD_TYPES.has((tmpl as FieldDef<unknown>).type)) {\n throw new DynamicFormError(\n `Simplified array \"${key}\" template contains a '${tmpl.type}' field (key: '${tmpl.key}'). ` +\n `Only leaf fields, rows, and groups are allowed as array children.`,\n );\n }\n }\n } else {\n const singleTemplate = template as FieldDef<unknown>;\n if (INVALID_ARRAY_CHILD_TYPES.has(singleTemplate.type)) {\n throw new DynamicFormError(\n `Simplified array \"${key}\" template has type '${singleTemplate.type}'. ` +\n `Only leaf fields, rows, and groups are allowed as array children.`,\n );\n }\n }\n}\n\n/** Expands a simplified array field into a full ArrayField + optional add button. */\nfunction expandSimplifiedArray(field: SimplifiedArrayField): ExpandedArray {\n const {\n template,\n value = [],\n addButton,\n removeButton,\n key,\n logic,\n minLength,\n maxLength,\n wrappers,\n skipAutoWrappers,\n skipDefaultWrappers,\n validators,\n validationMessages,\n required,\n validateWhenHidden,\n } = field;\n const isObjectTemplate = Array.isArray(template);\n const values = value as unknown[];\n\n // Validate template before expansion\n validateSimplifiedTemplate(field);\n\n // Build items from values\n const items: ArrayItemDefinition[] = values.map((v) => {\n if (isObjectTemplate) {\n return buildObjectItem(template as readonly ArrayAllowedChildren[], v as Record<string, unknown>, removeButton);\n }\n return buildPrimitiveItem(template as ArrayAllowedChildren, v);\n });\n\n // Build the add button template (item structure without values)\n // For primitive arrays, the add template is a single field (not wrapped in array)\n // so that handleAddFromEvent treats it as a primitive item\n const addTemplate: ArrayAllowedChildren | readonly ArrayAllowedChildren[] = isObjectTemplate\n ? buildObjectItemTemplate(template as readonly ArrayAllowedChildren[], removeButton)\n : (template as ArrayAllowedChildren);\n\n // For primitive arrays with remove buttons, store the remove button config\n // via Symbol metadata. The array component renders remove buttons alongside\n // each item without wrapping in a row, preserving flat primitive form values.\n const hasAutoRemove = !isObjectTemplate && removeButton !== false;\n\n // Construct the full ArrayField\n const arrayFieldObj: Record<string, unknown> = {\n key,\n type: 'array' as const,\n fields: items,\n };\n if (logic) {\n arrayFieldObj['logic'] = logic;\n }\n if (minLength !== undefined) {\n arrayFieldObj['minLength'] = minLength;\n }\n if (maxLength !== undefined) {\n arrayFieldObj['maxLength'] = maxLength;\n }\n if (wrappers !== undefined) {\n arrayFieldObj['wrappers'] = wrappers;\n }\n if (skipAutoWrappers !== undefined) {\n arrayFieldObj['skipAutoWrappers'] = skipAutoWrappers;\n }\n if (skipDefaultWrappers !== undefined) {\n arrayFieldObj['skipDefaultWrappers'] = skipDefaultWrappers;\n }\n // Container validators belong to the array itself, not to its items — carry\n // them onto the expanded ArrayField so the schema mapping still sees them.\n if (validators !== undefined) {\n arrayFieldObj['validators'] = validators;\n }\n if (validationMessages !== undefined) {\n arrayFieldObj['validationMessages'] = validationMessages;\n }\n if (required !== undefined) {\n arrayFieldObj['required'] = required;\n }\n if (validateWhenHidden !== undefined) {\n arrayFieldObj['validateWhenHidden'] = validateWhenHidden;\n }\n\n // Safe cast: we're constructing a valid ArrayField shape with key, type, and fields\n const arrayField = arrayFieldObj as unknown as FieldDef<unknown>;\n\n // Store normalization metadata via Symbol property instead of a runtime property.\n // `template` always gets populated so the array component can resolve untracked\n // items (e.g., from external form-value updates).\n //\n // For object templates, we must include the auto-generated remove button in the stored\n // template because object arrays embed the button inside each item's fields (via\n // buildObjectItem) rather than via the `autoRemoveButton` metadata. Without this,\n // items resolved from metadata would render without the remove button that\n // originally-declared items have. Primitive templates keep the button as separate\n // metadata and pass the raw template through — withAutoRemove() appends the button\n // at resolution time from autoRemoveButton.\n const primitiveFieldKey = !isObjectTemplate ? (template as ArrayAllowedChildren).key : undefined;\n const metadataTemplate = isObjectTemplate ? buildObjectItemTemplate(template as readonly ArrayAllowedChildren[], removeButton) : template;\n\n setNormalizedArrayMetadata(arrayFieldObj, {\n ...(hasAutoRemove && { autoRemoveButton: buildRemoveButton(removeButton) }),\n ...(primitiveFieldKey && { primitiveFieldKey }),\n template: metadataTemplate,\n });\n\n // Construct the add button (sibling, placed after the array)\n let addButtonField: FieldDef<unknown> | undefined;\n if (addButton !== false) {\n const buttonConfig = (typeof addButton === 'object' ? addButton : {}) as ArrayButtonConfig;\n // Safe cast: we're constructing a valid add-array-item field shape\n addButtonField = {\n key: `${key}__add`,\n type: 'add-array-item',\n label: buttonConfig.label ?? 'Add',\n arrayKey: key,\n template: addTemplate,\n ...(buttonConfig.props && { props: buttonConfig.props }),\n // Logic is intentionally shared with the array field so the add button\n // hides/shows together with the array (e.g., when a hidden condition applies).\n ...(logic && { logic }),\n } as unknown as FieldDef<unknown>;\n }\n\n return { arrayField, addButton: addButtonField };\n}\n\n/** Builds a primitive array item as a single FieldDef (not wrapped in array). */\nfunction buildPrimitiveItem(template: ArrayAllowedChildren, value: unknown): ArrayItemDefinition {\n return { ...template, value } as ArrayAllowedChildren;\n}\n\n/** Builds an object array item: template fields with values merged + optional remove button. */\nfunction buildObjectItem(\n template: readonly ArrayAllowedChildren[],\n valueObj: Record<string, unknown>,\n removeButton: ArrayButtonConfig | false | undefined,\n): ArrayItemDefinition {\n const fieldsWithValues = template.map(\n (templateField) =>\n ({\n ...templateField,\n ...(Object.hasOwn(valueObj, templateField.key) && { value: valueObj[templateField.key] }),\n }) as ArrayAllowedChildren,\n );\n\n if (removeButton === false) {\n return fieldsWithValues;\n }\n\n return [...fieldsWithValues, buildRemoveButton(removeButton)];\n}\n\n/** Builds the add button template for object items (template fields without values + remove button). */\nfunction buildObjectItemTemplate(\n template: readonly ArrayAllowedChildren[],\n removeButton: ArrayButtonConfig | false | undefined,\n): readonly ArrayAllowedChildren[] {\n if (removeButton === false) {\n return template;\n }\n\n return [...template, buildRemoveButton(removeButton)];\n}\n\n/** Builds a remove button field definition. */\nfunction buildRemoveButton(config: ArrayButtonConfig | undefined): ArrayAllowedChildren {\n const buttonConfig = (typeof config === 'object' ? config : {}) as ArrayButtonConfig;\n // Safe cast: remove-array-item fields are valid ArrayAllowedChildren but not in the static union\n return {\n key: '__remove',\n type: 'remove-array-item',\n label: buttonConfig.label ?? 'Remove',\n ...(buttonConfig.props && { props: buttonConfig.props }),\n } as unknown as ArrayAllowedChildren;\n}\n","import { detectFormMode, FormModeDetectionResult, isPageField } from '@ng-forge/dynamic-forms/internal';\nimport { RegisteredFieldTypes } from '@ng-forge/dynamic-forms/internal';\nimport { validatePageNesting } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormError } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Comprehensive form configuration validator that checks:\n * 1. Form mode consistency (paged vs non-paged)\n * 2. Page nesting rules\n * 3. Field placement constraints\n */\nexport class FormModeValidator {\n /**\n * Validates a form configuration and returns detailed validation results\n *\n * @param fields The form field definitions to validate\n * @returns Validation result with mode detection and error details\n */\n static validateFormConfiguration<TFields extends RegisteredFieldTypes[]>(fields: TFields): FormConfigurationValidationResult {\n const modeDetection = detectFormMode(fields);\n const additionalErrors: string[] = [];\n\n // Additional validation for paged forms\n if (modeDetection.mode === 'paged' && modeDetection.isValid) {\n // Validate each page field individually\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i];\n if (isPageField(field)) {\n if (!validatePageNesting(field)) {\n additionalErrors.push(\n `Page field at index ${i} (key: \"${field.key || 'unknown'}\") contains nested page fields, which is not allowed.`,\n );\n }\n }\n }\n }\n\n const allErrors = [...modeDetection.errors, ...additionalErrors];\n const isFullyValid = modeDetection.isValid && additionalErrors.length === 0;\n\n return {\n mode: modeDetection.mode,\n isValid: isFullyValid,\n errors: allErrors,\n warnings: this.generateWarnings(fields, modeDetection),\n };\n }\n\n /**\n * Validates form configuration and throws an error if invalid\n *\n * @param fields The form field definitions to validate\n * @throws Error with detailed validation messages if form is invalid\n */\n static validateFormConfigurationOrThrow<TFields extends RegisteredFieldTypes[]>(fields: TFields): void {\n const result = this.validateFormConfiguration(fields);\n\n if (!result.isValid) {\n const errorMessage = [`Invalid form configuration (${result.mode} mode):`, ...result.errors.map((error) => ` - ${error}`)].join(\n '\\n',\n );\n\n throw new DynamicFormError(errorMessage);\n }\n }\n\n /**\n * Generates helpful warnings for form configurations\n *\n * @param fields The form field definitions\n * @param modeDetection The mode detection result\n * @returns Array of warning messages\n */\n private static generateWarnings<TFields extends RegisteredFieldTypes[]>(\n fields: TFields,\n modeDetection: FormModeDetectionResult,\n ): string[] {\n const warnings: string[] = [];\n\n // Warn about single page forms\n if (modeDetection.mode === 'paged' && fields.length === 1) {\n warnings.push('Single page form detected. Consider using non-paged mode for better performance if page navigation is not needed.');\n }\n\n // Warn about empty pages\n if (modeDetection.mode === 'paged') {\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i];\n if (isPageField(field)) {\n if (!field.fields || field.fields.length === 0) {\n warnings.push(`Page field at index ${i} (key: \"${field.key || 'unknown'}\") contains no fields and will render as empty.`);\n }\n }\n }\n }\n\n return warnings;\n }\n}\n\n/** Extended validation result including warnings */\nexport interface FormConfigurationValidationResult extends FormModeDetectionResult {\n /** Array of warning messages that don't prevent form operation */\n warnings: string[];\n}\n\n/**\n * Convenience function for quick form mode validation\n *\n * @param fields The form field definitions to validate\n * @returns True if form configuration is valid, false otherwise\n */\nexport function isValidFormConfiguration<TFields extends RegisteredFieldTypes[]>(fields: TFields): boolean {\n return FormModeValidator.validateFormConfiguration(fields).isValid;\n}\n","import { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { FieldWithValidation } from '@ng-forge/dynamic-forms/internal';\nimport { FieldTypeDefinition, getFieldValueHandling } from '@ng-forge/dynamic-forms/internal';\nimport { hasChildFields, isGroupField } from '@ng-forge/dynamic-forms/internal';\nimport { normalizeFieldsArray } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormError } from '@ng-forge/dynamic-forms/internal';\nimport { Logger } from '@ng-forge/dynamic-forms/internal';\nimport { DEV_MODE } from '../dev-mode';\n\n/** Data collected during a single config traversal. */\ninterface ConfigTraversalData {\n /**\n * Dot-scoped paths (e.g. `'address.street'`) — checked for form-value uniqueness:\n * two leaves landing at the same form-value path are a real conflict.\n */\n keys: string[];\n /**\n * Underscore-projected DOM-ID paths (e.g. `'address_street'`) — checked for\n * DOM `id` / `data-testid` uniqueness. Catches the otherwise-silent collision\n * where a top-level key like `'foo_bar'` would render the same DOM id as a\n * leaf `'bar'` inside group `'foo'`.\n */\n domIds: string[];\n types: Set<string>;\n regexErrors: string[];\n /** Own keys of value-bearing fields containing a dot (unsupported — nest via group fields). */\n dottedKeys: string[];\n}\n\n/**\n * Collects all field keys, types, and validates regex patterns from a field tree\n * by recursively traversing containers (page, row, group, array).\n *\n * @param collectKeys - When false, the entire subtree skips key collection (used\n * when descending into an array container).\n */\nfunction collectFieldData(\n fields: FieldDef<unknown>[],\n data: ConfigTraversalData,\n registry: Map<string, FieldTypeDefinition>,\n pathPrefix: string,\n collectKeys = true,\n): void {\n for (const field of fields) {\n // Defensively skip only known non-include modes — unexpected/missing\n // valueHandling defaults back to participating in duplicate detection so a\n // mis-registered field type doesn't silently drop from collision checks.\n const valueHandling = field.type ? getFieldValueHandling(field.type, registry) : 'include';\n const participatesInValue = valueHandling !== 'exclude' && valueHandling !== 'flatten';\n\n // Dotted keys never nest (checked regardless of collectKeys, to cover array templates).\n if (field.key && field.key.includes('.') && participatesInValue) {\n data.dottedKeys.push(field.key);\n }\n\n if (collectKeys && field.key && participatesInValue) {\n const scopedKey = pathPrefix ? `${pathPrefix}.${field.key}` : field.key;\n data.keys.push(scopedKey);\n // Project to the DOM-ID format (dots → underscores) so we can detect\n // collisions like top-level `'foo_bar'` vs group `'foo'` + leaf `'bar'`.\n data.domIds.push(scopedKey.replace(/\\./g, '_'));\n }\n if (field.type) {\n data.types.add(field.type);\n }\n\n const fieldWithValidation = field as FieldWithValidation;\n if ('pattern' in field && typeof fieldWithValidation.pattern === 'string') {\n validateRegexPattern(fieldWithValidation.pattern, field.key || '<unknown>', data.regexErrors);\n }\n\n if ('validators' in field && fieldWithValidation.validators) {\n for (const validator of fieldWithValidation.validators) {\n if (validator.type === 'pattern' && 'value' in validator && typeof validator.value === 'string') {\n validateRegexPattern(validator.value, field.key || '<unknown>', data.regexErrors);\n }\n }\n }\n\n if (hasChildFields(field)) {\n // Array item fields share template keys across items by design — stop collecting keys\n // once inside an array. Types and regex patterns are still validated.\n const childCollectKeys = collectKeys && field.type !== 'array';\n // Only group containers extend the scoping path — page/row flatten into the parent\n // scope, and array items use dynamic indices that aren't statically knowable.\n const childPrefix = isGroupField(field) && field.key ? (pathPrefix ? `${pathPrefix}.${field.key}` : field.key) : pathPrefix;\n const children = normalizeFieldsArray(field.fields) as (FieldDef<unknown> | FieldDef<unknown>[])[];\n for (const child of children) {\n if (Array.isArray(child)) {\n collectFieldData(child as FieldDef<unknown>[], data, registry, childPrefix, childCollectKeys);\n } else {\n collectFieldData([child], data, registry, childPrefix, childCollectKeys);\n }\n }\n }\n }\n}\n\n/** Validates a single regex pattern string, collecting errors rather than throwing. */\nfunction validateRegexPattern(pattern: string, fieldKey: string, errors: string[]): void {\n try {\n new RegExp(pattern);\n } catch (e) {\n // Detail (field key + engine message) is dev-only; the pattern alone identifies it in prod.\n errors.push(\n DEV_MODE\n ? `Invalid regex pattern in validator for field '${fieldKey}': '${pattern}' — ${e instanceof Error ? e.message : String(e)}`\n : `Invalid regex pattern: '${pattern}'`,\n );\n }\n}\n\n/**\n * Validates that no duplicate field keys exist in the config.\n * Throws a DynamicFormError listing all duplicates if any are found.\n *\n * @throws {DynamicFormError} When duplicate keys are detected\n */\nfunction validateNoDuplicateKeys(allKeys: string[]): void {\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n\n for (const key of allKeys) {\n if (seen.has(key)) {\n duplicates.add(key);\n }\n seen.add(key);\n }\n\n if (duplicates.size > 0) {\n const duplicateList = Array.from(duplicates)\n .map((k) => `'${k}'`)\n .join(', ');\n // Throw is load-bearing; only the explanatory tail is dev-only.\n throw new DynamicFormError(\n DEV_MODE\n ? `Duplicate field keys detected: ${duplicateList}. Field keys must be unique within their group scope (the same key may appear inside different groups).`\n : `Duplicate field keys detected: ${duplicateList}.`,\n );\n }\n}\n\n/**\n * Validates that the underscore-projected DOM-ID namespace has no collisions.\n *\n * @throws {DynamicFormError} When two scoped paths project to the same DOM ID\n */\nfunction validateNoDomIdCollisions(domIds: string[]): void {\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n\n for (const id of domIds) {\n if (seen.has(id)) {\n duplicates.add(id);\n }\n seen.add(id);\n }\n\n if (duplicates.size > 0) {\n const duplicateList = Array.from(duplicates)\n .map((k) => `'${k}'`)\n .join(', ');\n // Throw is load-bearing; only the explanatory tail is dev-only.\n throw new DynamicFormError(\n DEV_MODE\n ? `DOM id collision detected for: ${duplicateList}. Group-nested keys are joined with '_' to form DOM ids ` +\n `(e.g. group 'foo' + leaf 'bar' renders as id='foo_bar'). A separate top-level key like 'foo_bar' or a different ` +\n `group/leaf pair that underscores to the same string will produce duplicate ids. Rename one of the colliding keys.`\n : `DOM id collision detected for: ${duplicateList}.`,\n );\n }\n}\n\n/**\n * Validates that every field type referenced in the config exists in the registry.\n * Logs a warning for unregistered types — unknown fields are skipped during rendering\n * rather than blocking the whole form (graceful degradation).\n */\nfunction validateFieldTypesRegistered(allTypes: Set<string>, registry: Map<string, FieldTypeDefinition>, logger: Logger): void {\n if (registry.size === 0) return;\n\n const unregistered: string[] = [];\n\n for (const type of allTypes) {\n if (!registry.has(type)) {\n unregistered.push(type);\n }\n }\n\n if (unregistered.length > 0) {\n const typeList = unregistered.map((t) => `'${t}'`).join(', ');\n logger.warn(\n `Unknown field type(s): ${typeList}. Register them via provideDynamicForm(...withXxxFields()) or a custom registry entry. These fields will be skipped during rendering.`,\n );\n }\n}\n\n/**\n * Validates a form config at bootstrap time, checking for:\n * - Duplicate field keys (throws — this is always a developer error)\n * - Unregistered field types (warns — form degrades gracefully, skipping unknown fields)\n * - Invalid regex patterns in validators (throws — invalid regex will cause runtime errors)\n *\n * @throws {DynamicFormError} When duplicate keys or invalid regex patterns are detected\n */\nexport function validateFormConfig(fields: FieldDef<unknown>[], registry: Map<string, FieldTypeDefinition>, logger: Logger): void {\n const data: ConfigTraversalData = {\n keys: [],\n domIds: [],\n types: new Set<string>(),\n regexErrors: [],\n dottedKeys: [],\n };\n\n collectFieldData(fields, data, registry, '');\n\n if (data.dottedKeys.length > 0) {\n const list = Array.from(new Set(data.dottedKeys))\n .map((k) => `'${k}'`)\n .join(', ');\n // Throw is load-bearing; only the explanatory tail is dev-only.\n throw new DynamicFormError(\n DEV_MODE\n ? `Field key(s) contain a dot: ${list}. Dotted keys are not supported — express nesting with 'group' fields ` +\n `(e.g. { type: 'group', key: 'address', fields: [{ type: 'input', key: 'city' }] }).`\n : `Field key(s) contain a dot: ${list}.`,\n );\n }\n\n validateNoDuplicateKeys(data.keys);\n validateNoDomIdCollisions(data.domIds);\n // Warn-only diagnostic — unknown types already degrade gracefully at render time.\n if (DEV_MODE) validateFieldTypesRegistered(data.types, registry, logger);\n\n if (data.regexErrors.length > 0) {\n throw new DynamicFormError(\n data.regexErrors.length === 1\n ? data.regexErrors[0]\n : `Invalid regex pattern(s) found:\\n${data.regexErrors.map((e) => ` - ${e}`).join('\\n')}`,\n );\n }\n}\n","import { AnyAddon } from '@ng-forge/dynamic-forms/internal';\nimport { AddonTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { FieldTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { AddonWarning } from './addon-warning';\n\n/**\n * Walk a field's addons; return the survivors plus a list of warnings for\n * anything dropped.\n *\n * @param field The field to validate.\n * @param fieldRegistry Snapshot of `FIELD_REGISTRY` map.\n * @param typeRegistry Snapshot of `ADDON_TYPE_REGISTRY` map.\n * @param source Whether the config originated from JSON (lenient drop\n * of code-only types) or inline TypeScript.\n */\nexport function validateFieldAddons(\n field: FieldDef<unknown>,\n fieldRegistry: ReadonlyMap<string, FieldTypeDefinition>,\n typeRegistry: ReadonlyMap<string, AddonTypeDefinition>,\n source: 'json' | 'inline',\n): { addons: AnyAddon[]; warnings: AddonWarning[] } {\n const warnings: AddonWarning[] = [];\n const incoming = field.addons;\n if (!incoming?.length) {\n return { addons: [], warnings };\n }\n\n const fieldType = field.type;\n const fieldDef = fieldRegistry.get(fieldType);\n if (!fieldDef) {\n warnings.push({ type: 'unknown-field-type', fieldKey: field.key, fieldType });\n return { addons: [], warnings };\n }\n\n const addonSupport = fieldDef.addons;\n if (!addonSupport) {\n warnings.push({ type: 'field-type-no-addon-support', fieldKey: field.key, fieldType });\n return { addons: [], warnings };\n }\n\n const allowedSlots = addonSupport.slots;\n const allowedTypes = addonSupport.allowedTypes;\n const registeredTypes = Array.from(typeRegistry.keys());\n\n const survivors: AnyAddon[] = [];\n for (const addon of incoming) {\n // Slot allowed?\n if (!allowedSlots.includes(addon.slot)) {\n warnings.push({\n type: 'unknown-slot',\n fieldKey: field.key,\n fieldType,\n slot: String(addon.slot),\n allowedSlots,\n });\n continue;\n }\n\n // Type registered? `AnyAddon.type` is already a string-literal union via\n // DynamicFormAddonRegistry; no need to cast.\n const typeDef = typeRegistry.get(addon.type);\n if (!typeDef) {\n warnings.push({\n type: 'unknown-type',\n fieldKey: field.key,\n addonType: addon.type,\n registeredTypes,\n });\n continue;\n }\n\n // Type whitelisted (if `allowedTypes` was set)?\n if (allowedTypes && !allowedTypes.includes(typeDef.type)) {\n warnings.push({\n type: 'type-not-allowed',\n fieldKey: field.key,\n fieldType,\n addonType: typeDef.type,\n allowedTypes,\n });\n continue;\n }\n\n // Code-only type dropped from JSON-source configs. A type opts out of\n // JSON-safety via `AddonTypeDefinition.jsonSafe: false` (defaults to true).\n if (source === 'json' && typeDef.jsonSafe === false) {\n warnings.push({\n type: 'code-only-type-in-json',\n fieldKey: field.key,\n addonType: typeDef.type,\n });\n continue;\n }\n\n // Multi-set XOR + JSON-source function stripping. Both runs operate on\n // a working copy via `ensureCopy()` so the original config isn't\n // mutated — the survivor pushed at the bottom is either the original\n // addon (no strips) or the sanitized copy.\n let sanitized = addon as unknown as Record<string, unknown>;\n let stripped = false;\n const ensureCopy = () => {\n if (!stripped) sanitized = { ...sanitized };\n stripped = true;\n };\n\n // Snapshot which click variants the original config declared BEFORE\n // any stripping. Computing variants AFTER function-strip would\n // underreport the multi-variant warning (`action` would silently\n // vanish from the reported list).\n const declaredVariants = (['preset', 'actionRef', 'action'] as const).filter((k) => sanitized[k] !== undefined);\n\n // JSON-source function strip — inline `action`/`hidden`/`disabled`/\n // `loading` functions can't round-trip through serialization, so they\n // get dropped here with a warning. Inline-source configs keep them.\n if (source === 'json') {\n const dropReactiveFn = (key: 'hidden' | 'disabled' | 'loading') => {\n if (typeof sanitized[key] === 'function') {\n ensureCopy();\n delete sanitized[key];\n warnings.push({\n type: 'code-only-action-in-json',\n fieldKey: field.key,\n reason: `function '${key}' on type '${typeDef.type}' (use a signal/observable in code, or omit in JSON)`,\n });\n }\n };\n if (typeof sanitized.action === 'function') {\n ensureCopy();\n delete sanitized.action;\n warnings.push({\n type: 'code-only-action-in-json',\n fieldKey: field.key,\n reason: `inline 'action' function on type '${typeDef.type}'`,\n });\n }\n dropReactiveFn('hidden');\n dropReactiveFn('disabled');\n dropReactiveFn('loading');\n }\n\n // Multi-set XOR — applies to BOTH inline and JSON sources. TypeScript\n // discriminated unions already reject multi-set at compile time, but\n // configs that bypass type-checking (loose `any`, runtime composition,\n // JSON parsing) still need defence-in-depth. Keep the first variant,\n // strip the rest; mirrors the runtime precedence\n // (preset > actionRef > action) so the chosen handler matches what\n // the dispatcher would have picked.\n if (declaredVariants.length > 1) {\n ensureCopy();\n for (const k of declaredVariants.slice(1)) delete sanitized[k];\n warnings.push({\n type: 'code-only-action-in-json',\n fieldKey: field.key,\n reason: `multiple click variants on type '${typeDef.type}' (${declaredVariants.join(', ')}); kept '${declaredVariants[0]}'`,\n });\n }\n\n if (stripped) {\n survivors.push(sanitized as unknown as AnyAddon);\n continue;\n }\n\n // Per-type shape validator (throws on violation).\n if (typeDef.validate) {\n try {\n typeDef.validate(addon, field.key);\n } catch (error) {\n warnings.push({\n type: 'shape-violation',\n fieldKey: field.key,\n addonType: typeDef.type,\n reason: error instanceof Error ? error.message : String(error),\n });\n continue;\n }\n }\n\n survivors.push(addon);\n }\n\n return { addons: survivors, warnings };\n}\n\n/**\n * Recursively walk a field tree, validating each field's addons. Returns a\n * sanitized copy of the input field array plus accumulated warnings.\n */\nexport function walkAndValidateAddons(\n fields: readonly FieldDef<unknown>[],\n fieldRegistry: ReadonlyMap<string, FieldTypeDefinition>,\n typeRegistry: ReadonlyMap<string, AddonTypeDefinition>,\n source: 'json' | 'inline',\n): { fields: FieldDef<unknown>[]; warnings: AddonWarning[] } {\n const allWarnings: AddonWarning[] = [];\n const sanitized = fields.map((field) => {\n let next: FieldDef<unknown> = field;\n\n if (field.addons?.length) {\n const { addons, warnings } = validateFieldAddons(field, fieldRegistry, typeRegistry, source);\n allWarnings.push(...warnings);\n next = { ...next, addons };\n }\n\n // Recurse into containers — every container field type carries its\n // children on a `fields` array.\n const children = (next as { fields?: unknown }).fields;\n if (Array.isArray(children)) {\n const { fields: visited, warnings } = walkAndValidateAddons(\n children as readonly FieldDef<unknown>[],\n fieldRegistry,\n typeRegistry,\n source,\n );\n allWarnings.push(...warnings);\n next = { ...next, fields: visited } as FieldDef<unknown>;\n }\n\n return next;\n });\n\n return { fields: sanitized, warnings: allWarnings };\n}\n","/** Reason an addon was dropped during validation. */\nexport type AddonWarning =\n | { type: 'unknown-field-type'; fieldKey: string; fieldType: string }\n | { type: 'field-type-no-addon-support'; fieldKey: string; fieldType: string }\n | { type: 'unknown-slot'; fieldKey: string; fieldType: string; slot: string; allowedSlots: readonly string[] }\n | { type: 'unknown-type'; fieldKey: string; addonType: string; registeredTypes: readonly string[] }\n | { type: 'type-not-allowed'; fieldKey: string; fieldType: string; addonType: string; allowedTypes: readonly string[] }\n | { type: 'shape-violation'; fieldKey: string; addonType: string; reason: string }\n | { type: 'code-only-type-in-json'; fieldKey: string; addonType: string }\n | { type: 'code-only-action-in-json'; fieldKey: string; reason: string };\n\n/**\n * Stable structural fingerprint for an `AddonWarning`, used by the\n * FormStateManager dedup cache. Includes every distinguishing field\n * (`type`, `fieldKey`, `addonType`/`slot`/`reason` as relevant) so warnings\n * for different fields or different addon types never collapse to one log\n * line — independent of the human-readable format which may change.\n */\nexport function addonWarningKey(w: AddonWarning): string {\n switch (w.type) {\n case 'unknown-field-type':\n return `${w.type}|${w.fieldKey}|${w.fieldType}`;\n case 'field-type-no-addon-support':\n return `${w.type}|${w.fieldKey}|${w.fieldType}`;\n case 'unknown-slot':\n return `${w.type}|${w.fieldKey}|${w.fieldType}|${w.slot}`;\n case 'unknown-type':\n return `${w.type}|${w.fieldKey}|${w.addonType}`;\n case 'type-not-allowed':\n return `${w.type}|${w.fieldKey}|${w.fieldType}|${w.addonType}`;\n case 'shape-violation':\n return `${w.type}|${w.fieldKey}|${w.addonType}|${w.reason}`;\n case 'code-only-type-in-json':\n return `${w.type}|${w.fieldKey}|${w.addonType}`;\n case 'code-only-action-in-json':\n return `${w.type}|${w.fieldKey}|${w.reason}`;\n }\n}\n\n/** Render an `AddonWarning` to a developer-friendly message. */\nexport function formatAddonWarning(w: AddonWarning): string {\n switch (w.type) {\n case 'unknown-field-type':\n return `Field '${w.fieldKey}': unknown field type '${w.fieldType}'. Addons dropped.`;\n case 'field-type-no-addon-support':\n return (\n `Field '${w.fieldKey}' (type: '${w.fieldType}'): this field type does not declare addon support. Addons dropped. ` +\n `If this is incorrect, add 'addons: { slots: [...] }' to the field type registration.`\n );\n case 'unknown-slot':\n return (\n `Field '${w.fieldKey}' (type: '${w.fieldType}'): slot '${w.slot}' is not supported. ` +\n `Allowed: ${w.allowedSlots.join(', ')}. Addon dropped.`\n );\n case 'unknown-type':\n return (\n `Field '${w.fieldKey}': addon type '${w.addonType}' is not registered. ` +\n `Did you forget withCustomAddon({ type: '${w.addonType}', ... })? ` +\n `Currently registered: ${w.registeredTypes.join(', ') || '(none)'}. Addon dropped.`\n );\n case 'type-not-allowed':\n return (\n `Field '${w.fieldKey}' (type: '${w.fieldType}'): addon type '${w.addonType}' is not in the allowed list. ` +\n `Allowed: ${w.allowedTypes.join(', ')}. Addon dropped.`\n );\n case 'shape-violation':\n return `Field '${w.fieldKey}': addon type '${w.addonType}' shape invalid: ${w.reason}. Addon dropped.`;\n case 'code-only-type-in-json':\n return `Field '${w.fieldKey}': addon type '${w.addonType}' is code-only and cannot be used with JSON-derived configs. Addon dropped.`;\n case 'code-only-action-in-json':\n return `Field '${w.fieldKey}': ${w.reason}. Use 'preset' or 'actionRef' instead. Addon dropped.`;\n }\n}\n","import { InjectionToken } from '@angular/core';\nimport { ResolvedValueExclusionConfig } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Injection token for global value exclusion defaults.\n *\n * @internal\n */\nexport const VALUE_EXCLUSION_DEFAULTS = new InjectionToken<ResolvedValueExclusionConfig>('VALUE_EXCLUSION_DEFAULTS', {\n providedIn: 'root',\n factory: () => ({\n excludeValueIfHidden: true,\n excludeValueIfDisabled: true,\n excludeValueIfReadonly: true,\n }),\n});\n","import { FieldTree } from '@angular/forms/signals';\nimport { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { isGroupField } from '@ng-forge/dynamic-forms/internal';\nimport { isArrayField } from '@ng-forge/dynamic-forms/internal';\nimport { FieldTypeDefinition, getFieldValueHandling } from '@ng-forge/dynamic-forms/internal';\nimport { ResolvedValueExclusionConfig, ValueExclusionConfig } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Resolves the effective exclusion config for a field using the 3-tier hierarchy:\n * Field > Form > Global. For each property, the most specific defined value wins.\n *\n * @param global - Global defaults from VALUE_EXCLUSION_DEFAULTS token\n * @param form - Form-level overrides from FormOptions (may be undefined per property)\n * @param field - Field-level overrides from FieldDef (may be undefined per property)\n * @returns Fully resolved config with all properties defined\n */\nexport function resolveExclusionConfig(\n global: ResolvedValueExclusionConfig,\n form: ValueExclusionConfig | undefined,\n field: ValueExclusionConfig | undefined,\n): ResolvedValueExclusionConfig {\n return {\n excludeValueIfHidden: field?.excludeValueIfHidden ?? form?.excludeValueIfHidden ?? global.excludeValueIfHidden,\n excludeValueIfDisabled: field?.excludeValueIfDisabled ?? form?.excludeValueIfDisabled ?? global.excludeValueIfDisabled,\n excludeValueIfReadonly: field?.excludeValueIfReadonly ?? form?.excludeValueIfReadonly ?? global.excludeValueIfReadonly,\n };\n}\n\n/** Returns whether any field has at least one effective value-exclusion axis enabled. */\nexport function hasEnabledValueExclusion(\n fields: readonly FieldDef<unknown>[],\n global: ResolvedValueExclusionConfig,\n form: ValueExclusionConfig | undefined,\n): boolean {\n return fields.some((field) => {\n const resolved = resolveExclusionConfig(global, form, field);\n if (resolved.excludeValueIfHidden || resolved.excludeValueIfDisabled || resolved.excludeValueIfReadonly) {\n return true;\n }\n\n return (\n isGroupField(field) && !!field.fields && hasEnabledValueExclusion(Object.values(field.fields) as FieldDef<unknown>[], global, form)\n );\n });\n}\n\n/**\n * Static exclusion state a field may have inherited from a discarded flatten\n * container (page/row) ancestor during flattening. See `FlattenedField`.\n */\ninterface FieldWithInheritedExclusion {\n readonly inheritedExclusionState?: {\n readonly hidden?: boolean;\n readonly disabled?: boolean;\n readonly readonly?: boolean;\n };\n}\n\n/** Keeps only declared value-bearing fields without consulting reactive field state. */\nfunction filterDeclaredValueShape(\n rawValue: Record<string, unknown>,\n fields: readonly FieldDef<unknown>[],\n registry: Map<string, FieldTypeDefinition>,\n): Record<string, unknown> {\n const kept: Record<string, unknown> = {};\n\n for (const field of fields) {\n const key = field.key;\n if (!key || !(key in rawValue)) continue;\n\n const valueHandling = getFieldValueHandling(field.type, registry);\n if (valueHandling === 'exclude' || valueHandling === 'flatten') continue;\n\n const value = rawValue[key];\n if (isGroupField(field) && field.fields && value !== null && typeof value === 'object' && !Array.isArray(value)) {\n kept[key] = filterDeclaredValueShape(value as Record<string, unknown>, Object.values(field.fields) as FieldDef<unknown>[], registry);\n continue;\n }\n\n kept[key] = value;\n }\n\n return kept;\n}\n\n/**\n * Determines whether a field's value should be excluded based on its reactive state,\n * the field def's static state (for fields whose `state.hidden()` isn't wired — e.g. groups,\n * or state inherited from a hidden page/row container that was flattened away), and the\n * resolved exclusion config.\n */\nfunction shouldExcludeField(field: FieldDef<unknown>, fieldState: FieldTree<unknown>, config: ResolvedValueExclusionConfig): boolean {\n const state = fieldState();\n const inherited = (field as FieldWithInheritedExclusion).inheritedExclusionState;\n\n const isHidden = state.hidden() || field.hidden === true || inherited?.hidden === true;\n if (config.excludeValueIfHidden && isHidden) {\n return true;\n }\n\n const isDisabled = state.disabled() || field.disabled === true || inherited?.disabled === true;\n if (config.excludeValueIfDisabled && isDisabled) {\n return true;\n }\n\n const isReadonly = state.readonly() || field.readonly === true || inherited?.readonly === true;\n if (config.excludeValueIfReadonly && isReadonly) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Filters form values based on field reactive state (hidden, disabled, readonly)\n * and the 3-tier exclusion config hierarchy.\n *\n * @param rawValue - The unfiltered form value object\n * @param schemaFields - Flattened schema fields from FormSetup (groups/arrays preserved, pages/rows unwrapped)\n * @param formTree - The Angular Signal Forms FieldTree, accessed as `formInstance[key]`\n * @param registry - Field type registry for valueHandling mode lookup\n * @param globalDefaults - Global exclusion defaults from VALUE_EXCLUSION_DEFAULTS\n * @param formOptions - Form-level exclusion overrides from FormOptions\n * @param exclusionEnabled - Precomputed exclusion capability for hot callers\n * @returns Filtered value with excluded field values omitted\n */\nexport function filterFormValue<T extends Record<string, unknown>>(\n rawValue: T,\n schemaFields: FieldDef<unknown>[],\n formTree: Record<string, FieldTree<unknown>>,\n registry: Map<string, FieldTypeDefinition>,\n globalDefaults: ResolvedValueExclusionConfig,\n formOptions: ValueExclusionConfig | undefined,\n exclusionEnabled = hasEnabledValueExclusion(schemaFields, globalDefaults, formOptions),\n): Partial<T> {\n // No exclusion axis enabled: skip the per-field state reads and config resolution, but still\n // strip non-value field types and undeclared keys, which the loop below does unconditionally.\n if (!exclusionEnabled) {\n return filterDeclaredValueShape(rawValue, schemaFields, registry) as Partial<T>;\n }\n\n const result: Record<string, unknown> = {};\n\n for (const field of schemaFields) {\n const key = field.key;\n if (!key) continue;\n\n // Skip fields that don't contribute to form values\n const valueHandling = getFieldValueHandling(field.type, registry);\n if (valueHandling === 'exclude' || valueHandling === 'flatten') continue;\n\n // If the key doesn't exist in the raw value, skip\n if (!(key in rawValue)) continue;\n\n // Resolve per-field exclusion config\n const fieldExclusion: ValueExclusionConfig = {\n excludeValueIfHidden: field.excludeValueIfHidden,\n excludeValueIfDisabled: field.excludeValueIfDisabled,\n excludeValueIfReadonly: field.excludeValueIfReadonly,\n };\n const resolvedConfig = resolveExclusionConfig(globalDefaults, formOptions, fieldExclusion);\n\n // Componentless field (no FieldTree) — decide from the static field def alone, then include if not excluded.\n const fieldState = formTree[key] as FieldTree<unknown> | undefined;\n if (!fieldState || typeof fieldState !== 'function') {\n const inherited = (field as FieldWithInheritedExclusion).inheritedExclusionState;\n const staticallyExcluded =\n (resolvedConfig.excludeValueIfHidden && (field.hidden === true || inherited?.hidden === true)) ||\n (resolvedConfig.excludeValueIfDisabled && (field.disabled === true || inherited?.disabled === true)) ||\n (resolvedConfig.excludeValueIfReadonly && (field.readonly === true || inherited?.readonly === true));\n if (!staticallyExcluded) {\n result[key] = rawValue[key];\n }\n continue;\n }\n\n // Check if this field should be excluded based on its state\n if (shouldExcludeField(field, fieldState, resolvedConfig)) {\n continue;\n }\n\n // Handle group fields: recurse into nested structure\n if (isGroupField(field) && field.fields) {\n const groupValue = rawValue[key] as Record<string, unknown> | undefined;\n if (groupValue && typeof groupValue === 'object') {\n const childFields = Object.values(field.fields) as FieldDef<unknown>[];\n const nestedTree = fieldState as unknown as Record<string, FieldTree<unknown>>;\n result[key] = filterFormValue(\n groupValue as Record<string, unknown>,\n childFields,\n nestedTree,\n registry,\n globalDefaults,\n formOptions,\n true,\n );\n } else {\n result[key] = groupValue;\n }\n continue;\n }\n\n // Handle array fields: if not excluded at array level, include entire array value\n // (v1: no per-item filtering)\n if (isArrayField(field)) {\n result[key] = rawValue[key];\n continue;\n }\n\n // Leaf field: include value\n result[key] = rawValue[key];\n }\n\n return result as Partial<T>;\n}\n","import { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { FieldTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { FormConfig } from '@ng-forge/dynamic-forms/internal';\nimport { RegisteredFieldTypes } from '@ng-forge/dynamic-forms/internal';\nimport { FormMode } from '@ng-forge/dynamic-forms/internal';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Discriminant constants\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Lifecycle state discriminants.\n *\n * @internal\n */\nexport const LifecycleState = {\n Uninitialized: 'uninitialized',\n Initializing: 'initializing',\n Ready: 'ready',\n Transitioning: 'transitioning',\n Destroyed: 'destroyed',\n} as const;\n\n/** Indexed access type for {@link LifecycleState} values. */\nexport type LifecycleStateType = (typeof LifecycleState)[keyof typeof LifecycleState];\n\n/**\n * Transition phase discriminants.\n *\n * @internal\n */\nexport const Phase = {\n Teardown: 'teardown',\n Applying: 'applying',\n Restoring: 'restoring',\n} as const;\n\n/** Indexed access type for {@link Phase} values. */\nexport type PhaseType = (typeof Phase)[keyof typeof Phase];\n\n/**\n * Action type discriminants.\n *\n * @internal\n */\nexport const Action = {\n Initialize: 'initialize',\n ConfigChange: 'config-change',\n SetupComplete: 'setup-complete',\n ValueCaptured: 'value-captured',\n TeardownComplete: 'teardown-complete',\n ApplyComplete: 'apply-complete',\n RestoreComplete: 'restore-complete',\n Destroy: 'destroy',\n} as const;\n\n/** Indexed access type for {@link Action} values. */\nexport type ActionType = (typeof Action)[keyof typeof Action];\n\n/**\n * Side effect type discriminants.\n *\n * @internal\n */\nexport const Effect = {\n CaptureValue: 'capture-value',\n WaitFrameBoundary: 'wait-frame-boundary',\n CreateForm: 'create-form',\n RestoreValues: 'restore-values',\n} as const;\n\n/** Indexed access type for {@link Effect} values. */\nexport type EffectType = (typeof Effect)[keyof typeof Effect];\n\n// ─────────────────────────────────────────────────────────────────────────────\n// State types\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** @internal */\nexport type FormLifecycleState<TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[]> =\n | FormLifecycleUninitialized\n | FormLifecycleInitializing<TFields>\n | FormLifecycleReady<TFields>\n | FormLifecycleTransitioning<TFields>\n | FormLifecycleDestroyed;\n\nexport interface FormLifecycleUninitialized {\n readonly type: (typeof LifecycleState)['Uninitialized'];\n}\n\nexport interface FormLifecycleInitializing<TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[]> {\n readonly type: (typeof LifecycleState)['Initializing'];\n readonly config: FormConfig<TFields>;\n}\n\nexport interface FormLifecycleReady<TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[]> {\n readonly type: (typeof LifecycleState)['Ready'];\n readonly config: FormConfig<TFields>;\n readonly formSetup: FormSetup;\n}\n\nexport type TransitionPhase = PhaseType;\n\nexport interface FormLifecycleTransitioning<TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[]> {\n readonly type: (typeof LifecycleState)['Transitioning'];\n readonly phase: TransitionPhase;\n readonly currentConfig: FormConfig<TFields>;\n readonly pendingConfig: FormConfig<TFields>;\n readonly preservedValue?: Record<string, unknown>;\n /** FormSetup from the ready state that initiated this transition */\n readonly currentFormSetup: FormSetup;\n /** FormSetup computed for the pending config (set when apply-complete fires) */\n readonly pendingFormSetup?: FormSetup;\n}\n\nexport interface FormLifecycleDestroyed {\n readonly type: (typeof LifecycleState)['Destroyed'];\n}\n\n/** @internal */\nexport interface FormSetup {\n /** Fields to render (flattened for non-paged, empty for paged). */\n readonly fields: FieldDef<unknown>[];\n /** All schema fields for validation (flattened from all pages/containers). */\n readonly schemaFields: FieldDef<unknown>[];\n readonly originalFields?: FieldDef<unknown>[];\n readonly defaultValues: Record<string, unknown>;\n readonly mode: FormMode;\n readonly registry: Map<string, FieldTypeDefinition>;\n}\n\n/**\n * Actions that can be dispatched to the state machine.\n *\n * @internal\n */\nexport type FormStateAction<TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[]> =\n | InitializeAction<TFields>\n | ConfigChangeAction<TFields>\n | SetupCompleteAction\n | ValueCapturedAction\n | TeardownCompleteAction\n | ApplyCompleteAction\n | RestoreCompleteAction\n | DestroyAction;\n\nexport interface InitializeAction<TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[]> {\n readonly type: (typeof Action)['Initialize'];\n readonly config: FormConfig<TFields>;\n}\n\nexport interface ConfigChangeAction<TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[]> {\n readonly type: (typeof Action)['ConfigChange'];\n readonly config: FormConfig<TFields>;\n}\n\nexport interface SetupCompleteAction {\n readonly type: (typeof Action)['SetupComplete'];\n readonly formSetup: FormSetup;\n}\n\nexport interface ValueCapturedAction {\n readonly type: (typeof Action)['ValueCaptured'];\n readonly value: Record<string, unknown>;\n}\n\nexport interface TeardownCompleteAction {\n readonly type: (typeof Action)['TeardownComplete'];\n}\n\nexport interface ApplyCompleteAction {\n readonly type: (typeof Action)['ApplyComplete'];\n readonly formSetup: FormSetup;\n}\n\nexport interface RestoreCompleteAction {\n readonly type: (typeof Action)['RestoreComplete'];\n}\n\nexport interface DestroyAction {\n readonly type: (typeof Action)['Destroy'];\n}\n\n/**\n * State transition record for debugging and testing.\n *\n * @internal\n */\nexport interface StateTransition<TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[]> {\n readonly from: FormLifecycleState<TFields>;\n readonly to: FormLifecycleState<TFields>;\n readonly action: FormStateAction<TFields>;\n readonly timestamp: number;\n}\n\n/**\n * Result of a state transition.\n *\n * @internal\n */\nexport interface TransitionResult<TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[]> {\n readonly state: FormLifecycleState<TFields>;\n readonly sideEffects: SideEffect[];\n}\n\n/**\n * Side effects to execute after state transition.\n *\n * @internal\n */\nexport type SideEffect =\n | { readonly type: (typeof Effect)['CaptureValue'] }\n | { readonly type: (typeof Effect)['WaitFrameBoundary'] }\n | { readonly type: (typeof Effect)['CreateForm'] }\n | { readonly type: (typeof Effect)['RestoreValues']; readonly values: Record<string, unknown> };\n\n/** Error from async field component loading. */\nexport interface FieldLoadingError {\n readonly fieldType: string;\n readonly fieldKey: string;\n readonly error: Error;\n}\n\n/** @internal */\nexport function isReadyState<TFields extends RegisteredFieldTypes[]>(\n state: FormLifecycleState<TFields>,\n): state is FormLifecycleReady<TFields> {\n return state.type === LifecycleState.Ready;\n}\n\n/** @internal */\nexport function isTransitioningState<TFields extends RegisteredFieldTypes[]>(\n state: FormLifecycleState<TFields>,\n): state is FormLifecycleTransitioning<TFields> {\n return state.type === LifecycleState.Transitioning;\n}\n\n/** @internal */\nexport function createUninitializedState(): FormLifecycleUninitialized {\n return { type: LifecycleState.Uninitialized };\n}\n\n/** @internal */\nexport function createInitializingState<TFields extends RegisteredFieldTypes[]>(\n config: FormConfig<TFields>,\n): FormLifecycleInitializing<TFields> {\n return { type: LifecycleState.Initializing, config };\n}\n\n/** @internal */\nexport function createReadyState<TFields extends RegisteredFieldTypes[]>(\n config: FormConfig<TFields>,\n formSetup: FormSetup,\n): FormLifecycleReady<TFields> {\n return { type: LifecycleState.Ready, config, formSetup };\n}\n\n/** @internal */\nexport function createTransitioningState<TFields extends RegisteredFieldTypes[]>(\n phase: TransitionPhase,\n currentConfig: FormConfig<TFields>,\n pendingConfig: FormConfig<TFields>,\n currentFormSetup: FormSetup,\n preservedValue?: Record<string, unknown>,\n pendingFormSetup?: FormSetup,\n): FormLifecycleTransitioning<TFields> {\n return { type: LifecycleState.Transitioning, phase, currentConfig, pendingConfig, currentFormSetup, preservedValue, pendingFormSetup };\n}\n\n/** @internal */\nexport function createDestroyedState(): FormLifecycleDestroyed {\n return { type: LifecycleState.Destroyed };\n}\n","import { afterNextRender, DestroyRef, Injector } from '@angular/core';\nimport { Observable, Subscriber } from 'rxjs';\n\n/**\n * Options for side effect execution.\n *\n * @internal\n */\nexport interface SideEffectOptions {\n /** Injector for accessing Angular services */\n readonly injector: Injector;\n /** DestroyRef for cleanup on component destruction */\n readonly destroyRef: DestroyRef;\n}\n\n/**\n * Scheduler for managing side effect timing in the state machine.\n * Provides blocking, frame-boundary (rAF), and after-render timing.\n *\n * @internal\n */\nexport class SideEffectScheduler {\n private readonly injector: Injector;\n private readonly abortController = new AbortController();\n\n /** Aborted when the owning component is destroyed. */\n private get destroyed(): boolean {\n return this.abortController.signal.aborted;\n }\n\n constructor(options: SideEffectOptions) {\n this.injector = options.injector;\n\n options.destroyRef.onDestroy(() => {\n this.abortController.abort();\n });\n }\n\n /** Executes a synchronous blocking effect. */\n executeBlocking<T>(effect: () => T): Observable<T> {\n return new Observable((subscriber: Subscriber<T>) => {\n if (this.destroyed) {\n subscriber.complete();\n return;\n }\n\n try {\n const result = effect();\n subscriber.next(result);\n subscriber.complete();\n } catch (error) {\n subscriber.error(error);\n }\n });\n }\n\n /**\n * Defers effect to next rAF (~16ms), giving CD and the async field resolution\n * pipeline time to settle before the state machine continues.\n */\n executeAtFrameBoundary<T>(effect: () => T, options?: { skipIf?: () => boolean }): Observable<T> {\n if (options?.skipIf?.()) {\n return this.executeBlocking(effect);\n }\n\n return new Observable((subscriber: Subscriber<T>) => {\n if (this.destroyed) {\n subscriber.complete();\n return;\n }\n\n const frameId = requestAnimationFrame(() => {\n if (this.destroyed) {\n subscriber.complete();\n return;\n }\n\n try {\n const result = effect();\n subscriber.next(result);\n subscriber.complete();\n } catch (error) {\n subscriber.error(error);\n }\n });\n\n // Cleanup on unsubscribe\n return () => {\n cancelAnimationFrame(frameId);\n };\n });\n }\n\n /** Executes effect after Angular's next render cycle via `afterNextRender`. */\n executeAfterRender<T>(effect: () => T): Observable<T> {\n return new Observable((subscriber: Subscriber<T>) => {\n if (this.destroyed) {\n subscriber.complete();\n return;\n }\n\n const local = new AbortController();\n\n afterNextRender(\n () => {\n if (local.signal.aborted || this.destroyed) {\n subscriber.complete();\n return;\n }\n\n try {\n const result = effect();\n subscriber.next(result);\n subscriber.complete();\n } catch (error) {\n subscriber.error(error);\n }\n },\n { injector: this.injector },\n );\n\n // afterNextRender can't be deregistered — AbortSignal makes the callback no-op\n return () => {\n local.abort();\n };\n });\n }\n}\n\n/** @internal */\nexport function createSideEffectScheduler(injector: Injector): SideEffectScheduler {\n const destroyRef = injector.get(DestroyRef);\n return new SideEffectScheduler({ injector, destroyRef });\n}\n","import { DestroyRef, Injector, signal, Signal, untracked, WritableSignal } from '@angular/core';\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\nimport { catchError, concatMap, EMPTY, Observable, of, Subject } from 'rxjs';\nimport { FormConfig } from '@ng-forge/dynamic-forms/internal';\nimport { Logger } from '@ng-forge/dynamic-forms/internal';\nimport { RegisteredFieldTypes } from '@ng-forge/dynamic-forms/internal';\nimport {\n Action,\n createDestroyedState,\n createInitializingState,\n createReadyState,\n createTransitioningState,\n createUninitializedState,\n Effect,\n FormLifecycleState,\n FormSetup,\n FormStateAction,\n isReadyState,\n isTransitioningState,\n LifecycleState,\n Phase,\n SideEffect,\n StateTransition,\n TransitionResult,\n} from './state-types';\nimport { assertNever } from '@ng-forge/dynamic-forms/internal';\nimport { SideEffectScheduler } from './side-effect-scheduler';\nimport { DEV_MODE } from '../utils/dev-mode';\n\n/**\n * Configuration for the form state machine.\n *\n * @internal\n */\nexport interface FormStateMachineConfig<TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[]> {\n /** Injector for Angular service access */\n readonly injector: Injector;\n /** DestroyRef for cleanup */\n readonly destroyRef: DestroyRef;\n /** Side effect scheduler for controlled timing */\n readonly scheduler: SideEffectScheduler;\n /** Callback to create form setup from config */\n readonly createFormSetup: (config: FormConfig<TFields>) => FormSetup;\n /** Callback to capture current form value */\n readonly captureValue: () => Record<string, unknown>;\n /** Callback to restore form value */\n readonly restoreValue: (values: Record<string, unknown>, validKeys: Set<string>) => void;\n /** Predicate returning true when the field pipeline has already settled (all components cached) */\n readonly isFieldPipelineSettled?: () => boolean;\n /** Signal indicating whether the form is currently submitting */\n readonly isSubmitting?: Signal<boolean>;\n /** Callback when form is created (for registration) */\n readonly onFormCreated?: (formSetup: FormSetup) => void;\n /** Logger instance for error reporting */\n readonly logger: Logger;\n /** Callback for logging/debugging state transitions */\n readonly onTransition?: (transition: StateTransition<TFields>) => void;\n /** Callback when an action fails and error recovery runs */\n readonly onError?: (error: unknown, action: FormStateAction<TFields>) => void;\n}\n\n/**\n * RxJS-based state machine for form lifecycle management.\n * Uses `concatMap` for sequential action processing.\n *\n * @internal\n */\nexport class FormStateMachine<TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[]> {\n private readonly config: FormStateMachineConfig<TFields>;\n private readonly actions$ = new Subject<FormStateAction<TFields>>();\n private readonly _state: WritableSignal<FormLifecycleState<TFields>>;\n\n /** Signal of current state - use this for deriving computed signals */\n readonly state: Signal<FormLifecycleState<TFields>>;\n\n /** Observable of current state - for RxJS interop */\n readonly state$: Observable<FormLifecycleState<TFields>>;\n\n /** Current state value (synchronous read) */\n get currentState(): FormLifecycleState<TFields> {\n return this._state();\n }\n\n constructor(config: FormStateMachineConfig<TFields>) {\n this.config = config;\n this._state = signal(createUninitializedState());\n this.state = this._state.asReadonly();\n this.state$ = toObservable(this._state, { injector: config.injector });\n\n this.setupActionProcessing();\n }\n\n /** Dispatches an action. Processed sequentially via `concatMap`. */\n dispatch(action: FormStateAction<TFields>): void {\n this.actions$.next(action);\n }\n\n /** Sets up sequential action processing via `concatMap`. */\n private setupActionProcessing(): void {\n this.actions$\n .pipe(\n concatMap((action) =>\n this.processAction(action).pipe(\n catchError((error) => {\n this.config.logger.error(`Action '${action.type}' failed:`, error);\n this.recoverFromError(error, action);\n return EMPTY;\n }),\n ),\n ),\n takeUntilDestroyed(this.config.destroyRef),\n )\n .subscribe();\n }\n\n /**\n * Processes a single action: computes next state (pure), updates `_state`,\n * then executes side effects. Effects may dispatch follow-up actions that\n * are queued via `concatMap` and go through the same transition pipeline.\n */\n private processAction(action: FormStateAction<TFields>): Observable<void> {\n const currentState = this._state();\n const result = this.computeTransition(currentState, action);\n\n this.config.onTransition?.({\n from: currentState,\n to: result.state,\n action,\n timestamp: Date.now(),\n });\n\n this._state.set(result.state);\n return this.executeSideEffects(result.sideEffects);\n }\n\n /**\n * Recovers from a failed action by reverting to the last stable state.\n * Initializing → Uninitialized, Transitioning → Ready (using current setup).\n */\n private recoverFromError(error: unknown, action: FormStateAction<TFields>): void {\n const state = this._state();\n\n if (state.type === LifecycleState.Initializing) {\n this._state.set(createUninitializedState());\n } else if (isTransitioningState(state)) {\n this._state.set(createReadyState(state.currentConfig, state.currentFormSetup));\n }\n\n this.config.onError?.(error, action);\n }\n\n /** Pure transition: current state + action → next state + side effects. */\n private computeTransition(state: FormLifecycleState<TFields>, action: FormStateAction<TFields>): TransitionResult<TFields> {\n switch (action.type) {\n case Action.Initialize:\n return this.handleInitialize(state, action.config);\n\n case Action.ConfigChange:\n return this.handleConfigChange(state, action.config);\n\n case Action.SetupComplete:\n return this.handleSetupComplete(state, action.formSetup as FormSetup);\n\n case Action.ValueCaptured:\n return this.handleValueCaptured(state, action.value);\n\n case Action.TeardownComplete:\n return this.handleTeardownComplete(state);\n\n case Action.ApplyComplete:\n return this.handleApplyComplete(state, action.formSetup as FormSetup);\n\n case Action.RestoreComplete:\n return this.handleRestoreComplete(state);\n\n case Action.Destroy:\n return this.handleDestroy();\n\n default:\n return assertNever(action);\n }\n }\n\n private handleInitialize(state: FormLifecycleState<TFields>, config: FormConfig<TFields>): TransitionResult<TFields> {\n if (state.type !== LifecycleState.Uninitialized) {\n return { state, sideEffects: [] };\n }\n\n return {\n state: createInitializingState(config),\n sideEffects: [{ type: Effect.CreateForm }],\n };\n }\n\n private handleConfigChange(state: FormLifecycleState<TFields>, config: FormConfig<TFields>): TransitionResult<TFields> {\n if (state.type === LifecycleState.Uninitialized) {\n return {\n state: createInitializingState(config),\n sideEffects: [{ type: Effect.CreateForm }],\n };\n }\n\n if (state.type === LifecycleState.Initializing) {\n return {\n state: createInitializingState(config),\n sideEffects: [{ type: Effect.CreateForm }],\n };\n }\n\n // Guard: reject config changes during active submission to prevent races\n // between the in-flight action Promise and form teardown/rebuild.\n if (this.config.isSubmitting?.()) {\n this.config.logger.warn('Config changed during active submission; ignoring. Apply config changes after submission completes.');\n return { state, sideEffects: [] };\n }\n\n if (isReadyState(state)) {\n return {\n state: createTransitioningState(Phase.Teardown, state.config, config, state.formSetup),\n sideEffects: [{ type: Effect.CaptureValue }, { type: Effect.WaitFrameBoundary }],\n };\n }\n\n if (isTransitioningState(state)) {\n // Already transitioning — update pending config (latest wins)\n return {\n state: createTransitioningState(\n state.phase,\n state.currentConfig,\n config,\n state.currentFormSetup,\n state.preservedValue,\n state.pendingFormSetup,\n ),\n sideEffects: [],\n };\n }\n\n return { state, sideEffects: [] };\n }\n\n private handleSetupComplete(state: FormLifecycleState<TFields>, formSetup: FormSetup): TransitionResult<TFields> {\n if (state.type === LifecycleState.Initializing) {\n return {\n state: createReadyState(state.config, formSetup),\n sideEffects: [],\n };\n }\n\n return { state, sideEffects: [] };\n }\n\n private handleValueCaptured(state: FormLifecycleState<TFields>, value: Record<string, unknown>): TransitionResult<TFields> {\n if (!isTransitioningState(state)) {\n return { state, sideEffects: [] };\n }\n\n return {\n state: createTransitioningState(\n state.phase,\n state.currentConfig,\n state.pendingConfig,\n state.currentFormSetup,\n value,\n state.pendingFormSetup,\n ),\n sideEffects: [],\n };\n }\n\n private handleTeardownComplete(state: FormLifecycleState<TFields>): TransitionResult<TFields> {\n if (!isTransitioningState(state) || state.phase !== Phase.Teardown) {\n return { state, sideEffects: [] };\n }\n\n return {\n state: createTransitioningState(\n Phase.Applying,\n state.currentConfig,\n state.pendingConfig,\n state.currentFormSetup,\n state.preservedValue,\n ),\n sideEffects: [{ type: Effect.CreateForm }],\n };\n }\n\n private handleApplyComplete(state: FormLifecycleState<TFields>, formSetup: FormSetup): TransitionResult<TFields> {\n if (!isTransitioningState(state) || state.phase !== Phase.Applying) {\n return { state, sideEffects: [] };\n }\n\n if (state.preservedValue && Object.keys(state.preservedValue).length > 0) {\n return {\n state: createTransitioningState(\n Phase.Restoring,\n state.currentConfig,\n state.pendingConfig,\n state.currentFormSetup,\n state.preservedValue,\n formSetup,\n ),\n sideEffects: [{ type: Effect.RestoreValues, values: state.preservedValue }],\n };\n }\n\n return {\n state: createReadyState(state.pendingConfig, formSetup),\n sideEffects: [],\n };\n }\n\n private handleRestoreComplete(state: FormLifecycleState<TFields>): TransitionResult<TFields> {\n if (!isTransitioningState(state) || state.phase !== Phase.Restoring) {\n return { state, sideEffects: [] };\n }\n\n // Diagnostic only — the `??` fallback below is what keeps the transition correct.\n if (DEV_MODE && !state.pendingFormSetup) {\n this.config.logger.warn(\n 'handleRestoreComplete: pendingFormSetup was not set — falling back to recomputing. ' +\n 'This indicates a bug in the transition flow.',\n );\n }\n const formSetup = state.pendingFormSetup ?? this.config.createFormSetup(state.pendingConfig);\n\n return {\n state: createReadyState(state.pendingConfig, formSetup),\n sideEffects: [],\n };\n }\n\n private handleDestroy(): TransitionResult<TFields> {\n return {\n state: createDestroyedState(),\n sideEffects: [],\n };\n }\n\n /**\n * Executes side effects in sequence. Effects may call `this.dispatch()` internally,\n * queuing follow-up actions into the same `concatMap` pipeline.\n */\n private executeSideEffects(effects: SideEffect[]): Observable<void> {\n if (effects.length === 0) {\n return of(undefined);\n }\n\n return effects.reduce(\n (chain$, effect) => chain$.pipe(concatMap(() => this.executeSideEffect(effect))),\n of(undefined) as Observable<void>,\n );\n }\n\n private executeSideEffect(effect: SideEffect): Observable<void> {\n const { scheduler } = this.config;\n\n switch (effect.type) {\n case Effect.CaptureValue: {\n return scheduler.executeBlocking(() => {\n const value = this.config.captureValue();\n this.dispatch({ type: Action.ValueCaptured, value });\n });\n }\n\n case Effect.WaitFrameBoundary: {\n return scheduler.executeAtFrameBoundary(\n () => {\n this.dispatch({ type: Action.TeardownComplete });\n },\n { skipIf: this.config.isFieldPipelineSettled },\n );\n }\n\n case Effect.CreateForm: {\n return scheduler.executeBlocking(() => {\n const state = untracked(() => this._state());\n\n let config: FormConfig<TFields> | undefined;\n if (state.type === LifecycleState.Initializing) {\n config = state.config;\n } else if (isTransitioningState(state) && state.phase === Phase.Applying) {\n config = state.pendingConfig;\n }\n\n if (!config) return;\n\n const formSetup = this.config.createFormSetup(config);\n this.config.onFormCreated?.(formSetup);\n\n if (state.type === LifecycleState.Initializing) {\n this.dispatch({ type: Action.SetupComplete, formSetup });\n } else if (isTransitioningState(state) && state.phase === Phase.Applying) {\n this.dispatch({ type: Action.ApplyComplete, formSetup });\n }\n });\n }\n\n case Effect.RestoreValues: {\n return scheduler.executeAfterRender(() => {\n const state = untracked(() => this._state());\n if (!isTransitioningState(state) || state.phase !== Phase.Restoring) return;\n\n // Diagnostic only — the `??` fallback below is what keeps the transition correct.\n if (DEV_MODE && !state.pendingFormSetup) {\n this.config.logger.warn('RestoreValues effect: pendingFormSetup was not set — falling back to recomputing.');\n }\n const formSetup = state.pendingFormSetup ?? this.config.createFormSetup(state.pendingConfig);\n\n // Restore a captured value only when the key survives the swap AND the field's type\n // is unchanged. A retyped key (e.g. input → select) must initialize to the new field's\n // declared default rather than inheriting the stale value from the old field type.\n // Keyed on top-level schemaFields, so a retype of a nested-group child is not tracked here.\n const oldTypeByKey = new Map<string, string>();\n for (const f of state.currentFormSetup.schemaFields) {\n if (f.key !== undefined) oldTypeByKey.set(f.key, f.type);\n }\n const validKeys = new Set<string>();\n for (const f of formSetup.schemaFields) {\n if (f.key !== undefined && oldTypeByKey.get(f.key) === f.type) validKeys.add(f.key);\n }\n\n this.config.restoreValue(effect.values, validKeys);\n this.dispatch({ type: Action.RestoreComplete });\n });\n }\n\n default:\n return assertNever(effect);\n }\n }\n}\n\n/** @internal */\nexport function createFormStateMachine<TFields extends RegisteredFieldTypes[]>(\n config: FormStateMachineConfig<TFields>,\n): FormStateMachine<TFields> {\n return new FormStateMachine(config);\n}\n","import {\n computed,\n DestroyRef,\n inject,\n injectAsync,\n Injectable,\n InjectionToken,\n Injector,\n linkedSignal,\n OnDestroy,\n resource,\n runInInjectionContext,\n signal,\n Signal,\n untracked,\n WritableSignal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { FieldTree, form, Schema } from '@angular/forms/signals';\nimport { EMPTY, filter, forkJoin, map, Observable, of, pipe, scan, switchMap, take } from 'rxjs';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\n\nimport { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { normalizeSimplifiedArrays } from '../utils/array-field/normalize-simplified-arrays';\nimport { DynamicFormError } from '@ng-forge/dynamic-forms/internal';\nimport { isGroupField } from '@ng-forge/dynamic-forms/internal';\nimport { isPageField, PageField } from '@ng-forge/dynamic-forms/internal';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { GoToPageEvent, PageNavigationOptions } from '../events/constants/go-to-page.event';\nimport { FormClearEvent } from '../events/constants/form-clear.event';\nimport { FormResetEvent } from '../events/constants/form-reset.event';\nimport { FormSubmitEvent } from '../events/constants/submit.event';\nimport { FieldSignalContext } from '@ng-forge/dynamic-forms/internal';\nimport { FIELD_SIGNAL_CONTEXT } from '@ng-forge/dynamic-forms/internal';\nimport { FieldTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { FormConfig, FormOptions } from '@ng-forge/dynamic-forms/internal';\nimport { RegisteredFieldTypes } from '@ng-forge/dynamic-forms/internal';\nimport { detectFormMode, FormMode } from '@ng-forge/dynamic-forms/internal';\nimport { InferFormModel } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayItemRegistryService } from '../core/registry/array-item-registry.service';\nimport { FunctionRegistryService } from '@ng-forge/dynamic-forms/internal';\nimport { SchemaRegistryService } from '../core/registry/schema-registry.service';\nimport { deepMergeDefaults, isEqual } from '@ng-forge/dynamic-forms/internal';\nimport { CONTAINER_FIELD_PROCESSORS } from '../utils/container-utils/container-field-processors';\nimport { derivedFromDeferred } from '@ng-forge/dynamic-forms/internal';\nimport { reconcileFields, ResolvedField, resolveField, resolveFieldSync } from '../utils/resolve-field/resolve-field';\nimport { FormModeValidator } from '../utils/form-validation/form-mode-validator';\nimport { injectFieldRegistry } from '../utils/inject-field-registry/inject-field-registry';\nimport { validateFormConfig } from '../utils/config-validation/config-validator';\nimport { walkAndValidateAddons } from '../utils/validate-form-config/validate-field-addons';\nimport { addonWarningKey, formatAddonWarning } from '../utils/validate-form-config/addon-warning';\nimport { ADDON_TYPE_REGISTRY } from '@ng-forge/dynamic-forms/internal';\nimport { VALUE_EXCLUSION_DEFAULTS } from '../providers/features/value-exclusion/value-exclusion.token';\nimport { filterFormValue, hasEnabledValueExclusion } from '../utils/value-filter/value-filter';\nimport { DEV_MODE } from '../utils/dev-mode';\nimport { ValueExclusionConfig } from '@ng-forge/dynamic-forms/internal';\n\nimport { Action, FieldLoadingError, FormSetup, isReadyState, isTransitioningState, LifecycleState, Phase } from './state-types';\nimport { createSideEffectScheduler } from './side-effect-scheduler';\nimport { createFormStateMachine, FormStateMachine } from './form-state-machine';\n\n/**\n * Shared deps holder injected by both DynamicForm and FormStateManager.\n * DynamicForm assigns its input signals to the holder's properties via an IIFE\n * field initializer (runs before FormStateManager is injected in declaration order);\n * FormStateManager reads them.\n *\n * @internal\n */\nexport interface FormStateDeps {\n config: Signal<FormConfig<RegisteredFieldTypes[]>> | null;\n formOptions: Signal<FormOptions | undefined> | null;\n value: WritableSignal<Partial<unknown> | undefined> | null;\n /**\n * Source mode forwarded to the addon validator at bootstrap. `'inline'`\n * (default) keeps every kind; `'json'` drops code-only kinds. Optional —\n * defaults to `'inline'` when omitted.\n */\n source: Signal<'inline' | 'json'> | null;\n}\n\n/** @internal */\nexport const FORM_STATE_DEPS = new InjectionToken<FormStateDeps>('FORM_STATE_DEPS');\n\n/** Casts a FieldTree to a record of per-key sub-trees. */\nfunction asFieldTreeRecord(tree: FieldTree<unknown>): Record<string, FieldTree<unknown>> {\n return tree as unknown as Record<string, FieldTree<unknown>>;\n}\n\n/** All-false baseline for the outward two-way binding filter — see `boundFormValue`. */\nconst BOUND_VALUE_EXCLUSION_BASELINE = {\n excludeValueIfHidden: false,\n excludeValueIfDisabled: false,\n excludeValueIfReadonly: false,\n} as const;\n\n/** Per-field axes that can drive value exclusion. */\ninterface FieldExclusionAxes {\n readonly hidden: boolean;\n readonly disabled: boolean;\n readonly readonly: boolean;\n}\n\n/** True when any of the three exclusion axes is asserted (i.e. the field could be filtered out of the bound model). */\nfunction isFieldExcluded(axes: FieldExclusionAxes | undefined): boolean {\n return !!axes && (axes.hidden || axes.disabled || axes.readonly);\n}\n\n/**\n * Recursively populates `out` with `dottedPath → exclusion axes` for every keyed field reachable\n * from `fields`, walking into groups so nested-leaf transitions can be detected. Arrays are\n * treated as leaves (whole-array filtering only — see value-filter v1 limitation).\n */\nfunction collectFieldStateSnapshot(\n fields: readonly FieldDef<unknown>[],\n treeRecord: Record<string, FieldTree<unknown>>,\n pathParts: readonly string[],\n out: Record<string, FieldExclusionAxes>,\n): void {\n for (const field of fields) {\n const key = field.key;\n if (!key) continue;\n const subtree = treeRecord[key];\n if (!subtree || typeof subtree !== 'function') continue;\n\n const state = subtree();\n const path = [...pathParts, key];\n out[path.join('.')] = { hidden: state.hidden(), disabled: state.disabled(), readonly: state.readonly() };\n\n if (isGroupField(field) && field.fields) {\n collectFieldStateSnapshot(field.fields as readonly FieldDef<unknown>[], asFieldTreeRecord(subtree), path, out);\n }\n }\n}\n\n/**\n * Reads a value from a nested object by dotted-path segments. Returns undefined\n * if any intermediate segment is missing or non-object.\n */\nfunction getValueAtPath(source: Record<string, unknown>, segments: readonly string[]): unknown {\n let current: unknown = source;\n for (const segment of segments) {\n if (current === null || typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n return current;\n}\n\n/**\n * Whether a value is worth capturing into the saved-hidden-value store. `NaN` (the number-input\n * default) is excluded — restoring it would re-leak the default into the bound model when the\n * field becomes visible again, defeating the bug fix.\n */\nfunction isRestoreRelevant(value: unknown): boolean {\n return !(typeof value === 'number' && Number.isNaN(value));\n}\n\n/**\n * Returns a new object with `value` set at the path described by `segments`.\n * Intermediate objects are cloned shallowly to preserve immutability of `target`.\n */\nfunction setValueAtPath(target: Record<string, unknown>, segments: readonly string[], value: unknown): Record<string, unknown> {\n if (segments.length === 0) return target;\n const [head, ...rest] = segments;\n const next = { ...target };\n if (rest.length === 0) {\n next[head] = value;\n } else {\n const child = target[head];\n const childObj = child !== null && typeof child === 'object' ? (child as Record<string, unknown>) : {};\n next[head] = setValueAtPath(childObj, rest, value);\n }\n return next;\n}\n\n/**\n * Central service that manages all form state and coordinates the form lifecycle.\n * Single source of truth for lifecycle state, field resolution, form signals, and events.\n *\n * @internal\n */\n@Injectable()\nexport class FormStateManager<\n TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[],\n TModel extends Record<string, unknown> = InferFormModel<TFields>,\n> implements OnDestroy {\n // ─────────────────────────────────────────────────────────────────────────────\n // Dependencies (injected)\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly injector = inject(Injector);\n private readonly destroyRef = inject(DestroyRef);\n private readonly logger = inject(DynamicFormLogger);\n private readonly eventBus = inject(EventBus);\n private readonly functionRegistry = inject(FunctionRegistryService);\n private readonly schemaRegistry = inject(SchemaRegistryService);\n // Optional so unit-test setups that drive FormStateManager directly without provideDynamicFormDI()\n // (e.g. mocked RootFormRegistryService specs) don't have to manually wire the registry. Real\n // DynamicForm usage always provides it via coreProviders; if you hit the dev warning below in\n // your own setup, you're using DynamicForm without provideDynamicFormDI() — fix the providers\n // chain rather than ignoring it.\n private readonly arrayItemRegistry = inject(ArrayItemRegistryService, { optional: true });\n\n /** Host component dependencies (config, formOptions, value). */\n private readonly deps = (() => {\n const raw = inject(FORM_STATE_DEPS);\n if (!raw.config || !raw.formOptions || !raw.value) {\n throw new DynamicFormError(\n 'FormStateDeps must be connected before FormStateManager is created. ' +\n 'Ensure DynamicForm assigns its input signals to FORM_STATE_DEPS.',\n );\n }\n // Safe cast: DynamicForm populates FormStateDeps with its concrete signals.\n // `source` is optional — `DynamicForm` always populates it, but other\n // callers of `FormStateManager` (e.g., specs) may omit it.\n return raw as {\n readonly config: Signal<FormConfig<TFields>>;\n readonly formOptions: Signal<FormOptions | undefined>;\n readonly value: WritableSignal<Partial<TModel> | undefined>;\n readonly source: Signal<'inline' | 'json'> | null;\n };\n })();\n\n /** Global value exclusion defaults. */\n private readonly valueExclusionDefaults = inject(VALUE_EXCLUSION_DEFAULTS);\n\n /** Field registry for loading components. */\n private readonly fieldRegistry = injectFieldRegistry();\n /** Addon-kind registry — feeds the addon validator at config-setup time. */\n private readonly addonKindRegistry = inject(ADDON_TYPE_REGISTRY);\n /**\n * Fingerprints of addon warnings emitted by the last config setup.\n * Used to skip re-logging warnings that already fired for the previous\n * config — avoids spam when the form swaps config repeatedly but the\n * addon issues haven't changed.\n */\n private lastAddonWarningKeys: Set<string> = new Set();\n\n // ─────────────────────────────────────────────────────────────────────────────\n // State Machine\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly scheduler = createSideEffectScheduler(this.injector);\n private readonly machine: FormStateMachine<TFields>;\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Memoized Functions\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly fieldProcessors = inject(CONTAINER_FIELD_PROCESSORS);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Internal State Signals\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Field loading errors accumulated during resolution. */\n readonly fieldLoadingErrors = signal<FieldLoadingError[]>([]);\n\n /**\n * Class-level form cache for the \"hold until settled\" pattern.\n * MUST be class-level — a local variable in the computed would reset on re-evaluation.\n * Mutable ref avoids a reactive cycle (form → isSettled → resolvedFields → form).\n */\n private readonly _formCache: { current: ReturnType<typeof form<TModel>> | undefined } = { current: undefined };\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Computed Signals - Derived from State Machine\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * The currently active config used for form rendering.\n * Teardown/Applying → old config, Restoring → new config.\n * Returns deps.config() in uninitialized state so the form schema is\n * available before the state machine dispatches 'initialize'.\n */\n readonly activeConfig = computed(() => {\n const state = this.machine.state();\n\n if (state.type === LifecycleState.Uninitialized) {\n return this.deps.config();\n }\n\n if (isReadyState(state)) return state.config;\n if (isTransitioningState(state)) {\n if (state.phase === Phase.Teardown || state.phase === Phase.Applying) return state.currentConfig;\n return state.pendingConfig;\n }\n if (state.type === LifecycleState.Initializing) return state.config;\n return undefined;\n });\n\n /** Current render phase: 'render' = showing form, 'teardown' = hiding old components. */\n readonly renderPhase = computed(() => {\n const state = this.machine.state();\n if (isTransitioningState(state) && state.phase === Phase.Teardown) return Phase.Teardown;\n return 'render';\n });\n\n /** Whether to render the form template. */\n readonly shouldRender = computed(() => this.activeConfig() !== undefined);\n\n /** Computed form mode detection with validation. */\n readonly formModeDetection = computed(() => {\n const config = this.activeConfig();\n if (!config) {\n return { mode: 'non-paged' as const, isValid: true, errors: [] };\n }\n\n return detectFormMode(config.fields || []);\n });\n\n /** Effective form options (merged from config and input). */\n readonly effectiveFormOptions = computed(() => {\n const config = this.activeConfig();\n const configOptions = config?.options || {};\n const inputOptions = this.deps.formOptions() ?? undefined;\n return { ...configOptions, ...inputOptions };\n });\n\n /**\n * A page the form has been asked to navigate to but that no pager has applied yet.\n * Held here because the orchestrator mounts behind the render gate: a request made on\n * `initialized` reaches the bus before that subscription exists, and would otherwise be\n * dropped. The orchestrator drains this once it can resolve visibility and validity.\n */\n readonly pendingPageRequest = signal<{ index: number; options?: PageNavigationOptions } | null>(null);\n\n /** Page field definitions (for paged forms). */\n readonly pageFieldDefinitions = computed(() => {\n const config = this.activeConfig();\n const mode = this.formModeDetection().mode;\n\n if (mode === 'paged' && config?.fields) {\n return config.fields.filter(isPageField);\n }\n\n return [] as PageField[];\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Computed Signals - Form Setup\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly rawFieldRegistry = computed(() => this.fieldRegistry.raw);\n\n /** Computed form setup — reads from the state machine, computed from config on bootstrap. */\n readonly formSetup = computed(() => {\n const registry = this.rawFieldRegistry();\n const state = this.machine.state();\n\n if (isReadyState(state)) {\n return state.formSetup;\n }\n\n if (isTransitioningState(state)) {\n if (state.phase === Phase.Restoring && state.pendingFormSetup) {\n return state.pendingFormSetup;\n }\n return state.currentFormSetup;\n }\n\n // Bootstrap path: compute form setup before the state machine dispatches 'initialize'.\n // Register validators/schemas here so they are available before the first form is built.\n // This is a controlled side effect: registerValidatorsFromConfig is idempotent and only\n // mutates external registries (SchemaRegistry, FunctionRegistry), not reactive state.\n // The state machine's createFormSetup callback handles registration for subsequent configs.\n const config = this.activeConfig();\n if (config) {\n this.registerValidatorsFromConfig(config as FormConfig<TFields>);\n }\n if (!config) {\n return this.createEmptyFormSetup(registry);\n }\n\n if (config.fields && config.fields.length > 0) {\n const modeDetection = this.formModeDetection();\n return this.createFormSetupFromConfig(config.fields as FieldDef<unknown>[], modeDetection.mode, registry);\n }\n\n return this.createEmptyFormSetup(registry);\n });\n\n /** Config generation that owns the current form setup. */\n private readonly formSetupConfig = computed(() => {\n const state = this.machine.state();\n\n if (isReadyState(state)) return state.config;\n if (isTransitioningState(state)) {\n if (state.phase === Phase.Restoring && state.pendingFormSetup) {\n return state.pendingConfig;\n }\n return state.currentConfig;\n }\n if (state.type === LifecycleState.Initializing) return state.config;\n if (state.type === LifecycleState.Uninitialized) return this.activeConfig();\n return undefined;\n });\n\n /** Active page state, retained across pager remounts and scoped to its form config. */\n readonly activePageState = linkedSignal<\n object | undefined,\n {\n config: object | undefined;\n initialized: boolean;\n index: number;\n }\n >({\n source: this.activeConfig,\n computation: (config) => ({ config, initialized: false, index: 0 }),\n });\n\n /** Default values computed from field definitions. */\n readonly defaultValues = linkedSignal(() => this.formSetup().defaultValues as TModel);\n\n /** Valid field keys — memoized separately so the Set isn't rebuilt on every keystroke. */\n private readonly validKeys = computed(() => {\n const schemaFields = this.formSetup().schemaFields;\n if (!schemaFields || schemaFields.length === 0) return undefined;\n\n const keys = new Set<string>();\n for (const field of schemaFields) {\n if (field.key === undefined) continue;\n keys.add(field.key);\n }\n return keys;\n });\n\n /** Whether outward value binding needs the reactive exclusion pipeline. */\n private readonly boundValueExclusionEnabled = computed(() => {\n const setup = this.formSetup();\n if (!setup.schemaFields || setup.schemaFields.length === 0) return false;\n\n const options = this.effectiveFormOptions();\n return hasEnabledValueExclusion(setup.schemaFields, BOUND_VALUE_EXCLUSION_BASELINE, {\n excludeValueIfHidden: options.excludeValueIfHidden,\n excludeValueIfDisabled: options.excludeValueIfDisabled,\n excludeValueIfReadonly: options.excludeValueIfReadonly,\n });\n });\n\n /** Whether filtered values need reactive hidden/disabled/readonly state reads. */\n private readonly valueExclusionEnabled = computed(() => {\n const setup = this.formSetup();\n if (!setup.schemaFields || setup.schemaFields.length === 0) return false;\n\n const options = this.effectiveFormOptions();\n return hasEnabledValueExclusion(setup.schemaFields, this.valueExclusionDefaults, {\n excludeValueIfHidden: options.excludeValueIfHidden,\n excludeValueIfDisabled: options.excludeValueIfDisabled,\n excludeValueIfReadonly: options.excludeValueIfReadonly,\n });\n });\n\n /**\n * Per-field exclusion-axis state (hidden/disabled/readonly) keyed by dotted path. Drives the\n * save-on-exclude effect's transition detection. Walks recursively into groups so nested-leaf\n * transitions are captured. Arrays are treated as leaves (whole-array preservation only).\n */\n private readonly fieldStateSnapshot = computed((): Record<string, FieldExclusionAxes> => {\n const schemaFields = this.formSetup().schemaFields;\n if (!this.formSchemaReady() || !this.boundValueExclusionEnabled() || !schemaFields || schemaFields.length === 0) return {};\n\n const snapshot: Record<string, FieldExclusionAxes> = {};\n collectFieldStateSnapshot(schemaFields, asFieldTreeRecord(this.form()), [], snapshot);\n return snapshot;\n });\n\n /**\n * Captured values for fields actively excluded from the bound model — either via\n * `excludeValueIfHidden`, `excludeValueIfDisabled`, or `excludeValueIfReadonly`. Restored when\n * the field becomes re-included (visible/enabled/editable). The save effect only writes here\n * when the field is being filtered out by `boundFormValue` — fields without explicit opt-in\n * never enter the store.\n */\n private readonly excludedValueStore = signal<Record<string, unknown>>({});\n\n /** Tracks per-path exclusion state across save-effect runs to detect newly-excluded fields. */\n private readonly prevFieldStateSnapshot = signal<Record<string, FieldExclusionAxes>>({});\n\n /** Pending reference pushed to `deps.value` by the outward-sync effect. */\n private readonly lastOutwardValue: { current: unknown; pending: boolean } = { current: undefined, pending: false };\n\n /** Last `deps.value` accepted as a genuine host change (memo for {@link externalValue}). */\n private readonly lastExternalValue: { current: unknown } = { current: undefined };\n\n /**\n * `deps.value` with our own outward sync filtered out. Without this the form reacts to the\n * value it just published: `entity` re-derives, which moves `boundFormValue`, which writes\n * `deps.value` again — a full whole-form merge per keystroke.\n */\n private readonly externalValue = computed<TModel>(() => {\n const incoming = this.deps.value();\n if (this.lastOutwardValue.pending && incoming === this.lastOutwardValue.current) {\n this.lastOutwardValue.pending = false;\n return this.lastExternalValue.current as TModel;\n }\n this.lastOutwardValue.pending = false;\n this.lastExternalValue.current = incoming;\n return incoming as TModel;\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Computed Signals - Entity & Form\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Entity (form value merged with defaults). */\n readonly entity = linkedSignal<TModel>(\n () => {\n // Read for the dependency only: `externalValue` filters our own echo so this does not\n // re-derive on the value it just published. Content comes from the live host signal,\n // because the filter's memo is stale by exactly the amount it suppressed.\n //\n // The narrowing this buys: a host write that `isEqual` considers identical to our last\n // outward push no longer re-derives the entity. That is correct here (the value is the\n // same) but it does mean host writes are deduplicated by value, not by reference.\n this.externalValue();\n const inputValue = untracked(() => this.deps.value()) as TModel;\n const defaults = this.defaultValues();\n const keys = this.validKeys();\n const saved = this.excludedValueStore();\n // Deep-merge so a partial nested object in `inputValue` (e.g. a group\n // value missing one of its declared sub-field keys) does not orphan\n // the absent sub-field in the Signal Forms validation graph.\n // Layer order: defaults < saved (excluded-field restorations) < inputValue.\n const withSaved = deepMergeDefaults(defaults as Record<string, unknown>, saved);\n const combined = deepMergeDefaults(withSaved, inputValue as Record<string, unknown>);\n\n if (keys) {\n const filtered: Record<string, unknown> = {};\n for (const key of Object.keys(combined)) {\n if (keys.has(key)) {\n filtered[key] = (combined as Record<string, unknown>)[key];\n }\n }\n return filtered as TModel;\n }\n\n return combined as TModel;\n },\n {\n debugName: 'FormStateManager.entity',\n equal: isEqual,\n },\n );\n\n /** Loads once, on the first non-empty schema request. Angular memoizes the import promise. */\n private readonly loadFormSchemaService = injectAsync(() => import('../core/form-schema.service'));\n\n /**\n * The actual schema request. There is deliberately no `requiresSchema` capability predicate:\n * the first value-bearing field requests the lazy compiler, including a plain field with no\n * optional rules. An empty form remains the only no-request case.\n */\n private readonly formSchemaRequest = computed(() => {\n const setup = this.formSetup();\n const config = this.activeConfig();\n if (!config || (!(setup.schemaFields?.length > 0) && !config.schema)) return undefined;\n\n return {\n fields: setup.schemaFields ?? [],\n registry: setup.registry,\n formLevelSchema: config.schema,\n validateWhenHidden: this.effectiveFormOptions().validateWhenHidden,\n };\n });\n\n /**\n * Declarative async bridge between `injectAsync()` and Signal Forms' synchronous schema API.\n * The service is resolved first; schema construction then runs synchronously in this form's\n * injection context. `resource()` also participates in Angular application stability and SSR.\n */\n private readonly formSchemaResource = resource({\n params: () => this.formSchemaRequest(),\n loader: async ({ params }) => {\n const schemaService = await this.loadFormSchemaService();\n // FormConfig stores Standard Schema input as `unknown`; TModel is inferred independently\n // from the same field definitions. The service stays model-agnostic and this boundary\n // restores the state manager's inferred type after compilation.\n return runInInjectionContext(this.injector, () => schemaService.create(params)) as Schema<TModel>;\n },\n });\n\n /**\n * Last schema the resource produced, with the request it was built from.\n *\n * A params change clears the resource's value, not just its status, so without this the form\n * would rebuild schemaless and then rebuild again. Instance-scoped, never module-scoped, so it\n * stays SSR-safe.\n */\n private readonly schemaCache: { current: { schema: Schema<TModel>; request: unknown } | undefined } = { current: undefined };\n\n /** Keeps {@link schemaCache} in step with the resource, and drops it on failure. */\n private readonly trackSchemaCache = computed(() => {\n const request = this.formSchemaRequest();\n if (!request) {\n this.schemaCache.current = undefined;\n return undefined;\n }\n if (this.formSchemaResource.status() === 'error') {\n this.schemaCache.current = undefined;\n return undefined;\n }\n if (this.formSchemaResource.hasValue()) {\n this.schemaCache.current = { schema: this.formSchemaResource.value(), request };\n }\n return this.schemaCache.current;\n });\n\n /** Whether the schema in hand was built from the current request. */\n readonly isSchemaCurrent = computed(() => {\n if (this.formSetupConfig() !== this.activeConfig()) return false;\n const request = this.formSchemaRequest();\n if (!request) return true;\n return this.trackSchemaCache()?.request === request;\n });\n\n /** True once a schema is in hand, or the compiler failed and the degraded path opened. */\n readonly formSchemaReady = computed(() => {\n if (this.formSetupConfig() !== this.activeConfig()) return false;\n if (!this.formSchemaRequest()) return true;\n if (this.formSchemaResource.status() === 'error') return true;\n return this.trackSchemaCache() !== undefined;\n });\n\n /** Schema derived from the current form config and field setup. */\n private readonly formSchema = computed((): Schema<TModel> | undefined => this.trackSchemaCache()?.schema);\n\n /** The Angular Signal Form instance. */\n readonly form = computed(() => {\n const schema = this.formSchema();\n const injector = this.injector;\n return untracked(() => (schema ? form(this.entity, schema, { injector }) : form(this.entity, { injector })));\n });\n\n /** Whether resolvedFields has caught up with fieldsSource (set in constructor). */\n private isFieldPipelineSettled: Signal<boolean>;\n\n /**\n * Field signal context injected into child components.\n * The `form` getter uses a \"hold until settled\" pattern: returns the cached\n * (old) form while resolvedFields != fieldsSource, preventing stale components\n * from accessing missing FieldTree references.\n */\n readonly fieldSignalContext: Signal<FieldSignalContext<TModel>> = computed(() => {\n const formSignal = this.form;\n const isSettled = () => this.isFieldPipelineSettled();\n const formCache = this._formCache;\n\n return {\n injector: this.injector,\n value: this.deps.value,\n defaultValues: this.defaultValues,\n get form() {\n const currentForm = formSignal();\n const settled = isSettled();\n\n if (!settled && formCache.current) {\n return formCache.current;\n }\n\n formCache.current = currentForm;\n return currentForm;\n },\n };\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Computed Signals - Form State\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Intermediate computed that unwraps the double-signal (form()()) once. */\n private readonly formInstance = computed(() => this.form()());\n\n /** Value of the model Signal Forms owns. */\n private readonly modelValue = computed(() => this.formInstance().value());\n\n /** Current form values (reactive). */\n readonly formValue = computed(() => this.modelValue() as TModel);\n\n /** Form values filtered by value exclusion rules. */\n readonly filteredFormValue = computed(() => {\n const rawValue = this.modelValue();\n const setup = this.formSetup();\n const schemaFields = setup.schemaFields;\n const options = this.effectiveFormOptions();\n\n if (!this.formSchemaReady() || !schemaFields || schemaFields.length === 0) {\n return rawValue;\n }\n\n // form() returns the FieldTree<TModel> — a callable with per-key sub-trees.\n // formInstance() returns form()() — the FieldState. We need the FieldTree for\n // per-field state access (e.g., formTree[key]() gives FieldState with hidden/disabled/readonly).\n const formTree = this.form();\n\n const formOptions: ValueExclusionConfig = {\n excludeValueIfHidden: options.excludeValueIfHidden,\n excludeValueIfDisabled: options.excludeValueIfDisabled,\n excludeValueIfReadonly: options.excludeValueIfReadonly,\n };\n\n // FieldTree<TModel> is structurally a callable that also exposes per-key sub-trees\n // via bracket access (e.g., formTree['fieldKey']). TypeScript's nominal typing for\n // FieldTree doesn't expose this index signature, so we use a helper cast.\n const fieldTreeRecord = asFieldTreeRecord(formTree);\n\n return filterFormValue(\n rawValue as Record<string, unknown>,\n schemaFields,\n fieldTreeRecord,\n setup.registry,\n this.valueExclusionDefaults,\n formOptions,\n this.valueExclusionEnabled(),\n );\n });\n\n /** Form value used for the outward two-way binding sync. */\n private readonly boundFormValue = computed(() => {\n const rawValue = this.modelValue();\n const setup = this.formSetup();\n const schemaFields = setup.schemaFields;\n const options = this.effectiveFormOptions();\n\n if (!this.formSchemaReady() || !schemaFields || schemaFields.length === 0) {\n return rawValue;\n }\n\n const formTree = this.form();\n const formOptions: ValueExclusionConfig = {\n excludeValueIfHidden: options.excludeValueIfHidden,\n excludeValueIfDisabled: options.excludeValueIfDisabled,\n excludeValueIfReadonly: options.excludeValueIfReadonly,\n };\n const fieldTreeRecord = asFieldTreeRecord(formTree);\n\n return filterFormValue(\n rawValue as Record<string, unknown>,\n schemaFields,\n fieldTreeRecord,\n setup.registry,\n BOUND_VALUE_EXCLUSION_BASELINE,\n formOptions,\n this.boundValueExclusionEnabled(),\n );\n });\n\n /** Whether the form is currently valid. */\n /**\n * Whether the form is currently valid.\n *\n * Schema compilation is lazy, so there is a window on first load, and after a config swap,\n * where no schema is in hand yet. Validity is unknown then rather than true: this reports\n * `false` and {@link invalid} reports `true` for that window, so a guard cannot let an\n * unvalidated form through. {@link dirty}, {@link touched} and {@link submitting} likewise\n * report `false` until the schema lands.\n */\n readonly valid = computed(() => this.formSchemaReady() && this.formSchemaResource.status() !== 'error' && this.formInstance().valid());\n\n /** Whether the form is currently invalid. True while the schema loads — see {@link valid}. */\n readonly invalid = computed(\n () => !this.formSchemaReady() || this.formSchemaResource.status() === 'error' || this.formInstance().invalid(),\n );\n\n /** Whether any form field has been modified. False while the schema loads — see {@link valid}. */\n readonly dirty = computed(() => this.formSchemaReady() && this.formInstance().dirty());\n\n /** Whether any form field has been touched (blurred). */\n readonly touched = computed(() => this.formSchemaReady() && this.formInstance().touched());\n\n /** Current validation errors from all fields. */\n readonly errors = computed(() => (this.formSchemaReady() ? this.formInstance().errors() : []));\n\n /** Whether the form is disabled (from options or form state). */\n readonly disabled = computed(() => {\n const optionsDisabled = this.effectiveFormOptions().disabled;\n const formDisabled = this.formSchemaReady() && this.formInstance().disabled();\n return optionsDisabled ?? formDisabled;\n });\n\n /** Whether the form is currently submitting. */\n readonly submitting = computed(() => this.formSchemaReady() && this.formInstance().submitting());\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Field Resolution\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Phase-aware field source that coordinates component lifecycle with form updates.\n * Teardown/Applying → intersection of old/new fields; Restoring → all new fields.\n */\n private readonly fieldsSource = computed(\n () => {\n const state = this.machine.state();\n\n if (isTransitioningState(state)) {\n const oldFields = state.currentConfig.fields ?? [];\n const newFields = state.pendingConfig.fields ?? [];\n const newKeys = new Set(newFields.map((f) => f.key));\n\n if (state.phase === Phase.Teardown || state.phase === Phase.Applying) {\n return oldFields.filter((f) => newKeys.has(f.key));\n }\n\n if (state.phase === Phase.Restoring) {\n return state.pendingFormSetup?.fields ?? this.formSetup().fields;\n }\n }\n\n return this.formSetup().fields;\n },\n {\n equal: (a, b) => {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n return a.every((field, i) => field === b[i]);\n },\n },\n );\n\n /** Injector for field components with FIELD_SIGNAL_CONTEXT. */\n private readonly fieldInjector = computed(() =>\n Injector.create({\n parent: this.injector,\n providers: [{ provide: FIELD_SIGNAL_CONTEXT, useValue: this.fieldSignalContext() }],\n }),\n );\n\n /** Resolved fields ready for rendering. */\n readonly resolvedFields: Signal<ResolvedField[]>;\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Event Streams (for outputs)\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Stream of submit events when form is valid.\n *\n * Typed as the full inferred model. The emitted payload is `filteredFormValue()`,\n * so when `excludeValueIfHidden` / `excludeValueIfDisabled` / `excludeValueIfReadonly`\n * are enabled a field that is hidden/disabled/readonly at submit time is omitted at\n * runtime while the type still lists it. Those options default off, so the type is\n * accurate for the common case; this matches the long-standing `as TModel` cast below.\n */\n readonly submitted$: Observable<TModel>;\n\n /** Stream of reset events. */\n readonly reset$: Observable<void>;\n\n /** Stream of clear events. */\n readonly cleared$: Observable<void>;\n\n /** Emits once when the state machine reaches 'ready'. Useful for tests. */\n get ready$(): Observable<void> {\n return this.machine.state$.pipe(\n filter(isReadyState),\n take(1),\n map(() => undefined),\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Constructor\n // ─────────────────────────────────────────────────────────────────────────────\n\n constructor() {\n this.resolvedFields = derivedFromDeferred(\n this.fieldsSource,\n pipe(\n switchMap((fields) => {\n if (!fields || fields.length === 0) {\n return of([] as (ResolvedField | undefined)[]);\n }\n\n const registry = this.rawFieldRegistry();\n const injector = this.fieldInjector();\n\n const syncContext = {\n getLoadedComponent: (type: string) => this.fieldRegistry.getLoadedComponent(type),\n registry,\n injector,\n };\n\n // Hybrid: resolve cached fields sync, only await uncached ones\n const results: (ResolvedField | undefined)[] = new Array(fields.length);\n const asyncIndexes: number[] = [];\n const asyncObs: Observable<ResolvedField | undefined>[] = [];\n\n const onError = (fieldDef: FieldDef<unknown>, error: unknown) => {\n const fieldKey = fieldDef.key || '<no key>';\n this.fieldLoadingErrors.update((errors) => [\n ...errors,\n {\n fieldType: fieldDef.type,\n fieldKey,\n error: error instanceof Error ? error : new Error(String(error)),\n },\n ]);\n this.logger.error(\n `Failed to load component for field type '${fieldDef.type}' (key: ${fieldKey}). ` +\n `Ensure the field type is registered in your field registry.`,\n error,\n );\n };\n\n for (let i = 0; i < fields.length; i++) {\n const f = fields[i];\n const def = this.fieldRegistry.getType(f.type);\n const isCached = !def?.loadComponent || this.fieldRegistry.getLoadedComponent(f.type);\n\n if (isCached) {\n results[i] = resolveFieldSync(f, syncContext);\n } else {\n asyncIndexes.push(i);\n asyncObs.push(\n resolveField(f, {\n loadTypeComponent: (type: string) => this.fieldRegistry.loadTypeComponent(type),\n registry,\n injector,\n destroyRef: this.destroyRef,\n onError,\n }),\n );\n }\n }\n\n if (asyncObs.length === 0) {\n return of(results);\n }\n\n return forkJoin(asyncObs).pipe(\n map((asyncResults) => {\n for (let j = 0; j < asyncResults.length; j++) {\n results[asyncIndexes[j]] = asyncResults[j];\n }\n return results;\n }),\n );\n }),\n map((fields) => fields.filter((f): f is ResolvedField => f !== undefined)),\n scan(reconcileFields, [] as ResolvedField[]),\n ),\n { initialValue: [] as ResolvedField[], injector: this.injector },\n ) as Signal<ResolvedField[]>;\n\n // Length comparison works because reconcileFields preserves ordering and\n // fieldsSource changes atomically during transitions (lengths won't match until settled).\n this.isFieldPipelineSettled = computed(() => {\n return this.fieldsSource().length === this.resolvedFields().length;\n });\n\n this.submitted$ = this.eventBus.on<FormSubmitEvent>('submit').pipe(\n filter(() => {\n if (!this.valid()) {\n this.logger.debug('Form submitted while invalid, not emitting to (submitted) output');\n return false;\n }\n return true;\n }),\n // switchMap is intentional here: mapping is synchronous (reads signals, no async Promise).\n // The exhaustMap concern in createSubmissionHandler does not apply to this path.\n switchMap(() => {\n const config = this.activeConfig();\n const submissionConfig = config?.submission;\n\n if (submissionConfig?.action) {\n this.logger.warn(\n 'Both `submission.action` and `(submitted)` output are configured. ' +\n 'When using `submission.action`, the `(submitted)` output will not emit. ' +\n 'Use either `submission.action` OR `(submitted)`, not both.',\n );\n return EMPTY;\n }\n\n return of(this.filteredFormValue() as TModel);\n }),\n takeUntilDestroyed(this.destroyRef),\n );\n\n this.reset$ = this.eventBus.on<FormResetEvent>('form-reset').pipe(\n map(() => undefined as void),\n takeUntilDestroyed(this.destroyRef),\n );\n\n this.cleared$ = this.eventBus.on<FormClearEvent>('form-clear').pipe(\n map(() => undefined as void),\n takeUntilDestroyed(this.destroyRef),\n );\n\n // Record page requests here rather than only in the pager, so one made before the\n // orchestrator mounts survives until it can be applied.\n this.eventBus\n .on<GoToPageEvent>('go-to-page')\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((event) => this.pendingPageRequest.set({ index: event.pageIndex, options: event.options }));\n\n // Create the state machine eagerly\n this.machine = createFormStateMachine<TFields>({\n injector: this.injector,\n destroyRef: this.destroyRef,\n scheduler: this.scheduler,\n logger: this.logger,\n createFormSetup: (config) => {\n this.registerValidatorsFromConfig(config);\n return this.createFormSetupFromConfig(\n (config.fields as FieldDef<unknown>[]) ?? [],\n detectFormMode(config.fields ?? []).mode,\n this.rawFieldRegistry(),\n );\n },\n captureValue: () => this.formValue() as Record<string, unknown>,\n isSubmitting: this.submitting,\n isFieldPipelineSettled: () => this.isFieldPipelineSettled(),\n restoreValue: (values, validKeys) => {\n const filtered: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(values)) {\n if (validKeys.has(key)) {\n filtered[key] = val;\n }\n }\n // Strip any captured key that did NOT survive the swap (dropped or retyped). The stale\n // value lingers in `deps.value` from before teardown, and `entity` layers it on top of\n // the new field's default — so a retyped key would otherwise inherit the old value\n // instead of initializing to its declared default. `values` is the full captured\n // snapshot, so any captured key absent from `validKeys` must be removed from the model.\n this.deps.value.update((current) => {\n const next = { ...current, ...filtered } as Record<string, unknown>;\n for (const key of Object.keys(values)) {\n if (!validKeys.has(key)) delete next[key];\n }\n return next as Partial<TModel>;\n });\n },\n onTransition: (transition) => {\n this.logger.debug('State transition:', transition.from.type, '→', transition.to.type, transition.action.type);\n },\n onError: (error, action) => {\n this.logger.error(`State machine error recovery triggered for action '${action.type}':`, error);\n },\n });\n\n runInInjectionContext(this.injector, () => {\n this.setupEffects();\n this.setupEventHandlers();\n });\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Public Methods\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Updates the form value model. */\n updateValue(value: Partial<TModel>): void {\n this.deps.value.set(value);\n }\n\n /** Resets the form to default values. */\n reset(): void {\n const rootField = this.form()();\n this.excludedValueStore.set({});\n const defaults = this.defaultValues();\n (rootField.value as WritableSignal<TModel>).set(defaults);\n this.deps.value.set(defaults as Partial<TModel>);\n rootField.reset();\n }\n\n /** Clears the form to empty state. */\n clear(): void {\n const rootField = this.form()();\n this.excludedValueStore.set({});\n const emptyValue = {} as TModel;\n (rootField.value as WritableSignal<TModel>).set(emptyValue);\n this.deps.value.set(emptyValue);\n rootField.reset();\n }\n\n /** Triggers form submission. */\n submit(): void {\n this.eventBus.dispatch(FormSubmitEvent);\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Private Methods - Setup\n // ─────────────────────────────────────────────────────────────────────────────\n\n private setupEffects(): void {\n explicitEffect([this.formSchemaResource.error], ([error]) => {\n if (error) {\n this.logger.error('Failed to compile the form schema; rendering without validation and blocking submission.', error);\n }\n });\n\n explicitEffect([this.deps.config], ([config]) => {\n this.fieldLoadingErrors.set([]);\n\n const state = this.machine.currentState;\n if (state.type === LifecycleState.Uninitialized) {\n this.machine.dispatch({ type: Action.Initialize, config });\n } else {\n this.machine.dispatch({ type: Action.ConfigChange, config });\n }\n });\n\n // Save-on-exclude: capture entity values for fields that boundFormValue is actively\n // filtering out via any of the three axes (hidden / disabled / readonly), so they can be\n // restored when the field becomes re-included. The transition fires once per \"no axis\n // asserted → at least one axis asserted\" edge; subsequent axis changes while still excluded\n // are no-ops. Comparing entity vs bound at the path limits the store to fields that are\n // actually being filtered — fields without explicit opt-in never enter the store and never\n // participate in the entity merge. `NaN` values are skipped: they're the number-input default\n // and would re-leak via the merge once the field becomes re-included.\n explicitEffect([this.fieldStateSnapshot], ([snapshot]) => {\n const currentSaved = this.excludedValueStore();\n const currentEntity = this.entity() as Record<string, unknown>;\n const boundValue = this.boundFormValue() as Record<string, unknown>;\n const prev = this.prevFieldStateSnapshot();\n let newSaved = currentSaved;\n\n for (const [path, axes] of Object.entries(snapshot)) {\n if (isFieldExcluded(axes) && !isFieldExcluded(prev[path])) {\n const segments = path.split('.');\n const inEntity = getValueAtPath(currentEntity, segments);\n const inBound = getValueAtPath(boundValue, segments);\n if (inEntity !== undefined && inBound === undefined && isRestoreRelevant(inEntity)) {\n newSaved = setValueAtPath(newSaved, segments, inEntity);\n }\n }\n }\n this.prevFieldStateSnapshot.set({ ...snapshot });\n\n if (newSaved !== currentSaved && !isEqual(newSaved, currentSaved)) {\n this.excludedValueStore.set(newSaved);\n }\n });\n\n // Schema change resets the saved store + transition tracker so values from a stale schema\n // can't leak into the new one. Also drops every per-array slot in the registry so a fresh\n // schema starts with an empty template/itemOrder/id-counter state.\n let warnedAboutMissingArrayRegistry = false;\n explicitEffect([this.formSetup], () => {\n this.prevFieldStateSnapshot.set({});\n if (Object.keys(this.excludedValueStore()).length > 0) {\n this.excludedValueStore.set({});\n }\n if (this.arrayItemRegistry) {\n this.arrayItemRegistry.clearAll();\n } else if (DEV_MODE && !warnedAboutMissingArrayRegistry) {\n warnedAboutMissingArrayRegistry = true;\n this.logger.warn(\n 'ArrayItemRegistryService was not provided to FormStateManager. ' +\n 'Array fields will lose dynamically-added item templates across hide/show cycles. ' +\n 'This usually means DynamicForm was bootstrapped without provideDynamicFormDI() — ' +\n 'check your providers chain.',\n );\n }\n });\n\n // Outward sync uses boundFormValue (honors only explicit excludeValueIf* opt-ins) so\n // global defaults that target submission output don't reshape the host's bound model.\n explicitEffect([this.boundFormValue], ([currentBound]) => {\n const currentValue = this.deps.value();\n if (!isEqual(currentBound, currentValue)) {\n // Record before writing so `externalValue` can recognise the echo. Only\n // `lastOutwardValue` — writing `lastExternalValue` here turned its memo into a\n // poisoned cache that returned a fresh object every keystroke, which notified\n // `entity` anyway. It is now written solely inside `externalValue`.\n this.lastOutwardValue.current = currentBound;\n this.lastOutwardValue.pending = true;\n this.deps.value.set(currentBound as TModel);\n }\n });\n\n // Reporting only — nothing downstream reads the result, so the whole validator\n // (FormModeValidator + page-nesting checks) tree-shakes out of production.\n if (DEV_MODE) {\n explicitEffect([this.activeConfig], ([config]) => {\n if (!config) return;\n const validation = FormModeValidator.validateFormConfiguration(config.fields || []);\n if (!validation.isValid) {\n this.logger.error('Invalid form configuration:', validation.errors);\n }\n if (validation.warnings.length > 0) {\n this.logger.warn('Form configuration warnings:', validation.warnings);\n }\n });\n }\n }\n\n private setupEventHandlers(): void {\n this.eventBus\n .on<FormResetEvent>('form-reset')\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this.reset());\n\n this.eventBus\n .on<FormClearEvent>('form-clear')\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this.clear());\n }\n\n private registerValidatorsFromConfig({ customFnConfig, schemas }: FormConfig<TFields>): void {\n if (schemas) {\n schemas.forEach((schema) => {\n this.schemaRegistry.registerSchema(schema);\n });\n }\n\n if (!customFnConfig) {\n return;\n }\n\n if (customFnConfig.customFunctions) {\n Object.entries(customFnConfig.customFunctions).forEach(([name, fn]) => {\n this.functionRegistry.registerCustomFunction(name, fn);\n });\n }\n\n if (customFnConfig.derivations) {\n this.functionRegistry.setDerivationFunctions(customFnConfig.derivations);\n }\n\n if (customFnConfig.asyncDerivations) {\n this.functionRegistry.setAsyncDerivationFunctions(customFnConfig.asyncDerivations);\n }\n if (customFnConfig.asyncConditions) {\n this.functionRegistry.setAsyncConditionFunctions(customFnConfig.asyncConditions);\n }\n\n this.functionRegistry.setValidators(customFnConfig.validators);\n this.functionRegistry.setAsyncValidators(customFnConfig.asyncValidators);\n this.functionRegistry.setHttpValidators(customFnConfig.httpValidators);\n }\n\n private createFormSetupFromConfig(fields: FieldDef<unknown>[], mode: FormMode, registry: Map<string, FieldTypeDefinition>): FormSetup {\n const normalizedFields = normalizeSimplifiedArrays(fields);\n // Two validation passes run after normalization so simplified array templates\n // are already expanded into full ArrayField.fields and reachable during traversal:\n // 1. Structural — duplicate keys, unknown field types, invalid regex patterns.\n // 2. Addon pass below — strips invalid/unsupported addons with lenient warnings.\n validateFormConfig(normalizedFields, registry, this.logger);\n\n // Addon pass — strip invalid / unsupported addon entries and log a warning\n // for each one dropped. Lenient by design: the form keeps rendering even\n // when a JSON-source config ships an addon the FE doesn't understand.\n //\n // Warnings are deduped across consecutive config setups: a warning that\n // already fired for the previous config is skipped, so swapping config\n // back and forth doesn't spam the console.\n const source = this.deps.source?.() ?? 'inline';\n const { fields: sanitizedFields, warnings: addonWarnings } = walkAndValidateAddons(\n normalizedFields,\n registry,\n this.addonKindRegistry,\n source,\n );\n // Diagnostics only — the addon *filtering* above is what's load-bearing.\n // Gated so `addonWarningKey`/`formatAddonWarning` tree-shake out of prod builds.\n if (DEV_MODE) {\n const nextKeys = new Set<string>();\n for (const w of addonWarnings) {\n // Dedup uses a structural fingerprint so different fields with the\n // same warning category never collide; the rendered message is what\n // we log.\n const key = addonWarningKey(w);\n nextKeys.add(key);\n if (!this.lastAddonWarningKeys.has(key)) {\n this.logger.warn(formatAddonWarning(w));\n }\n }\n this.lastAddonWarningKeys = nextKeys;\n }\n const validatedFields = sanitizedFields as FieldDef<unknown>[];\n\n const flattenedFields = this.fieldProcessors.memoizedFlattenFields(validatedFields, registry);\n const flattenedFieldsForRendering = this.fieldProcessors.memoizedFlattenFieldsForRendering(validatedFields, registry);\n const fieldsById = this.fieldProcessors.memoizedKeyBy(flattenedFields);\n const defaultValues = this.fieldProcessors.memoizedDefaultValues(fieldsById, registry);\n const fieldsToRender = mode === 'paged' ? [] : flattenedFieldsForRendering;\n\n return {\n fields: fieldsToRender,\n schemaFields: flattenedFields,\n originalFields: fields,\n defaultValues,\n mode,\n registry,\n };\n }\n\n private createEmptyFormSetup(registry: Map<string, FieldTypeDefinition>): FormSetup {\n return {\n fields: [],\n schemaFields: [],\n defaultValues: {} as Record<string, unknown>,\n mode: 'non-paged' as const,\n registry,\n };\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────────────────────────\n\n ngOnDestroy(): void {\n this.machine.dispatch({ type: Action.Destroy });\n }\n}\n"],"mappings":"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"}