/**
 * @license Angular v21.1.4
 * (c) 2010-2026 Google LLC. https://angular.dev/
 * License: MIT
 */

import * as i0 from '@angular/core';
import { ɵFormFieldBindingOptions as _FormFieldBindingOptions, InjectionToken, Injector, ɵCONTROL as _CONTROL, ɵɵcontrolCreate as __controlCreate, ɵcontrolUpdate as _controlUpdate, Signal, ɵFieldState as _FieldState, Provider, WritableSignal, DestroyableInjector } from '@angular/core';
import * as _angular_forms from '@angular/forms';
import { AbstractControl, ValidationErrors, FormControlStatus, ControlValueAccessor, ValidatorFn } from '@angular/forms';
import { StandardSchemaV1 } from '@standard-schema/spec';

/**
 * Represents a combination of `NgControl` and `AbstractControl`.
 *
 * Note: We have this separate interface, rather than implementing the relevant parts of the two
 * controls with something like `InteropNgControl implements Pick<NgControl, ...>, Pick<AbstractControl, ...>`
 * because it confuses the internal JS minifier which can cause collisions in field names.
 */
interface CombinedControl {
    value: any;
    valid: boolean;
    invalid: boolean;
    touched: boolean;
    untouched: boolean;
    disabled: boolean;
    enabled: boolean;
    errors: ValidationErrors | null;
    pristine: boolean;
    dirty: boolean;
    status: FormControlStatus;
    control: AbstractControl<any, any>;
    valueAccessor: ControlValueAccessor | null;
    hasValidator(validator: ValidatorFn): boolean;
    updateValueAndValidity(): void;
}
/**
 * A fake version of `NgControl` provided by the `Field` directive. This allows interoperability
 * with a wider range of components designed to work with reactive forms, in particular ones that
 * inject the `NgControl`. The interop control does not implement *all* properties and methods of
 * the real `NgControl`, but does implement some of the most commonly used ones that have a clear
 * equivalent in signal forms.
 */
declare class InteropNgControl implements CombinedControl {
    protected field: () => FieldState<unknown>;
    constructor(field: () => FieldState<unknown>);
    readonly control: AbstractControl<any, any>;
    get value(): any;
    get valid(): boolean;
    get invalid(): boolean;
    get pending(): boolean | null;
    get disabled(): boolean;
    get enabled(): boolean;
    get errors(): ValidationErrors | null;
    get pristine(): boolean;
    get dirty(): boolean;
    get touched(): boolean;
    get untouched(): boolean;
    get status(): FormControlStatus;
    valueAccessor: ControlValueAccessor | null;
    hasValidator(validator: ValidatorFn): boolean;
    updateValueAndValidity(): void;
}

interface FormFieldBindingOptions extends _FormFieldBindingOptions {
    /**
     * Focuses the binding.
     *
     * If not specified, Signal Forms will attempt to focus the host element of the `FormField` when
     * asked to focus this binding.
     */
    focus?: VoidFunction;
}
/**
 * Lightweight DI token provided by the {@link FormField} directive.
 *
 * @category control
 * @experimental 21.0.0
 */
declare const FORM_FIELD: InjectionToken<FormField<unknown>>;
/**
 * Binds a form `FieldTree` to a UI control that edits it. A UI control can be one of several things:
 * 1. A native HTML input or textarea
 * 2. A signal forms custom control that implements `FormValueControl` or `FormCheckboxControl`
 * 3. A component that provides a `ControlValueAccessor`. This should only be used for backwards
 *    compatibility with reactive forms. Prefer options (1) and (2).
 *
 * This directive has several responsibilities:
 * 1. Two-way binds the field state's value with the UI control's value
 * 2. Binds additional forms related state on the field state to the UI control (disabled, required, etc.)
 * 3. Relays relevant events on the control to the field state (e.g. marks touched on blur)
 * 4. Provides a fake `NgControl` that implements a subset of the features available on the
 *    reactive forms `NgControl`. This is provided to improve interoperability with controls
 *    designed to work with reactive forms. It should not be used by controls written for signal
 *    forms.
 *
 * @category control
 * @experimental 21.0.0
 */
declare class FormField<T> {
    readonly element: HTMLElement;
    readonly injector: Injector;
    readonly formField: i0.InputSignal<FieldTree<T>>;
    readonly state: i0.Signal<[T] extends [_angular_forms.AbstractControl<any, any, any>] ? CompatFieldState<T, string | number> : FieldState<T, string | number>>;
    private readonly bindingOptions;
    readonly [_CONTROL]: {
        readonly create: typeof __controlCreate;
        readonly update: typeof _controlUpdate;
    };
    private config;
    /** Any `ControlValueAccessor` instances provided on the host element. */
    private readonly controlValueAccessors;
    /** A lazily instantiated fake `NgControl`. */
    private interopNgControl;
    /** Lazily instantiates a fake `NgControl` for this form field. */
    protected getOrCreateNgControl(): InteropNgControl;
    /**
     * Registers this `FormField` as a binding on its associated `FieldState`.
     *
     * This method should be called at most once for a given `FormField`. A `FormField` placed on a
     * custom control (`FormUiControl`) automatically registers that custom control as a binding.
     */
    registerAsBinding(bindingOptions?: FormFieldBindingOptions): void;
    /** Focuses this UI control. */
    focus(): void;
    static ɵfac: i0.ɵɵFactoryDeclaration<FormField<any>, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<FormField<any>, "[formField]", never, { "formField": { "alias": "formField"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
}

/**
 * Sets a value for the {@link MetadataKey} for this field.
 *
 * This value is combined via a reduce operation defined by the particular key,
 * since multiple rules in the schema might set values for it.
 *
 * @param path The target path to set the metadata for.
 * @param key The metadata key
 * @param logic A function that receives the `FieldContext` and returns a value for the metadata.
 * @template TValue The type of value stored in the field the logic is bound to.
 * @template TKey The type of metadata key.
 * @template TPathKind The kind of path the logic is bound to (a root path, child path, or item of an array)
 *
 * @category logic
 * @experimental 21.0.0
 */
declare function metadata<TValue, TKey extends MetadataKey<any, any, any>, TPathKind extends PathKind = PathKind.Root>(path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>, key: TKey, logic: NoInfer<LogicFn<TValue, MetadataSetterType<TKey>, TPathKind>>): TKey;
/**
 * A reducer that determines the accumulated value for a metadata key by reducing the individual
 * values contributed from `metadata()` rules.
 *
 * @template TAcc The accumulated type of the reduce operation.
 * @template TItem The type of the individual items that are reduced over.
 * @experimental 21.0.2
 */
interface MetadataReducer<TAcc, TItem> {
    /** The reduce function. */
    reduce: (acc: TAcc, item: TItem) => TAcc;
    /** Gets the initial accumulated value. */
    getInitial: () => TAcc;
}
declare const MetadataReducer: {
    /** Creates a reducer that accumulates a list of its individual item values. */
    readonly list: <TItem>() => MetadataReducer<TItem[], TItem | undefined>;
    /** Creates a reducer that accumulates the min of its individual item values. */
    readonly min: () => MetadataReducer<number | undefined, number | undefined>;
    /** Creates a reducer that accumulates a the max of its individual item values. */
    readonly max: () => MetadataReducer<number | undefined, number | undefined>;
    /** Creates a reducer that logically or's its accumulated value with each individual item value. */
    readonly or: () => MetadataReducer<boolean, boolean>;
    /** Creates a reducer that logically and's its accumulated value with each individual item value. */
    readonly and: () => MetadataReducer<boolean, boolean>;
    /** Creates a reducer that always takes the next individual item value as the accumulated value. */
    readonly override: typeof override;
};
declare function override<T>(): MetadataReducer<T | undefined, T>;
declare function override<T>(getInitial: () => T): MetadataReducer<T, T>;
/**
 * Represents metadata that is aggregated from multiple parts according to the key's reducer
 * function. A value can be contributed to the aggregated value for a field using an
 * `metadata` rule in the schema. There may be multiple rules in a schema that contribute
 * values to the same `MetadataKey` of the same field.
 *
 * @template TRead The type read from the `FieldState` for this key
 * @template TWrite The type written to this key using the `metadata()` rule
 * @template TAcc The type of the reducer's accumulated value.
 *
 * @experimental 21.0.0
 */
declare class MetadataKey<TRead, TWrite, TAcc> {
    readonly reducer: MetadataReducer<TAcc, TWrite>;
    readonly create: ((s: Signal<TAcc>) => TRead) | undefined;
    private brand;
    /** Use {@link reducedMetadataKey}. */
    protected constructor(reducer: MetadataReducer<TAcc, TWrite>, create: ((s: Signal<TAcc>) => TRead) | undefined);
}
/**
 * Extracts the the type that can be set into the given metadata key type using the `metadata()` rule.
 *
 * @template TKey The `MetadataKey` type
 *
 * @experimental 21.0.0
 */
type MetadataSetterType<TKey> = TKey extends MetadataKey<any, infer TWrite, any> ? TWrite : never;
/**
 * Creates a metadata key used to contain a computed value.
 * The last value set on a given field tree node overrides any previously set values.
 *
 * @template TWrite The type written to this key using the `metadata()` rule
 *
 * @experimental 21.0.0
 */
declare function createMetadataKey<TWrite>(): MetadataKey<Signal<TWrite | undefined>, TWrite, TWrite | undefined>;
/**
 * Creates a metadata key used to contain a computed value.
 *
 * @param reducer The reducer used to combine individually set values into the final computed value.
 * @template TWrite The type written to this key using the `metadata()` rule
 * @template TAcc The type of the reducer's accumulated value.
 *
 * @experimental 21.0.0
 */
declare function createMetadataKey<TWrite, TAcc>(reducer: MetadataReducer<TAcc, TWrite>): MetadataKey<Signal<TAcc>, TWrite, TAcc>;
/**
 * Creates a metadata key that exposes a managed value based on the accumulated result of the values
 * written to the key. The accumulated value takes the last value set on a given field tree node,
 * overriding any previously set values.
 *
 * @param create A function that receives a signal of the accumulated value and returns the managed
 *   value based on it. This function runs during the construction of the `FieldTree` node,
 *   and runs in the injection context of that node.
 * @template TRead The type read from the `FieldState` for this key
 * @template TWrite The type written to this key using the `metadata()` rule
 *
 * @experimental 21.0.0
 */
declare function createManagedMetadataKey<TRead, TWrite>(create: (s: Signal<TWrite | undefined>) => TRead): MetadataKey<TRead, TWrite, TWrite | undefined>;
/**
 * Creates a metadata key that exposes a managed value based on the accumulated result of the values
 * written to the key.
 *
 * @param create A function that receives a signal of the accumulated value and returns the managed
 *   value based on it. This function runs during the construction of the `FieldTree` node,
 *   and runs in the injection context of that node.
 * @param reducer The reducer used to combine individual value written to the key,
 *   this will determine the accumulated value that the create function receives.
 * @template TRead The type read from the `FieldState` for this key
 * @template TWrite The type written to this key using the `metadata()` rule
 * @template TAcc The type of the reducer's accumulated value.
 *
 * @experimental 21.0.0
 */
declare function createManagedMetadataKey<TRead, TWrite, TAcc>(create: (s: Signal<TAcc>) => TRead, reducer: MetadataReducer<TAcc, TWrite>): MetadataKey<TRead, TWrite, TAcc>;
/**
 * A {@link MetadataKey} representing whether the field is required.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare const REQUIRED: MetadataKey<Signal<boolean>, boolean, boolean>;
/**
 * A {@link MetadataKey} representing the min value of the field.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare const MIN: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
/**
 * A {@link MetadataKey} representing the max value of the field.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare const MAX: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
/**
 * A {@link MetadataKey} representing the min length of the field.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare const MIN_LENGTH: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
/**
 * A {@link MetadataKey} representing the max length of the field.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare const MAX_LENGTH: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
/**
 * A {@link MetadataKey} representing the patterns the field must match.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare const PATTERN: MetadataKey<Signal<RegExp[]>, RegExp | undefined, RegExp[]>;

/**
 * Symbol used to retain generic type information when it would otherwise be lost.
 */
declare const ɵɵTYPE: unique symbol;
/**
 * A type that represents either a single value of type `T` or a readonly array of `T`.
 * @template T The type of the value(s).
 *
 * @experimental 21.0.0
 */
type OneOrMany<T> = T | readonly T[];
/**
 * The kind of `FieldPath` (`Root`, `Child` of another `FieldPath`, or `Item` in a `FieldPath` array)
 *
 * @experimental 21.0.0
 */
type PathKind = PathKind.Root | PathKind.Child | PathKind.Item;
declare namespace PathKind {
    /**
     * The `PathKind` for a `FieldPath` that is at the root of its field tree.
     */
    interface Root {
        /**
         * The `ɵɵTYPE` is constructed to allow the `extends` clause on `Child` and `Item` to narrow the
         * type. Another way to think about this is, if we have a function that expects this kind of
         * path, the `ɵɵTYPE` lists the kinds of path we are allowed to pass to it.
         */
        [ɵɵTYPE]: 'root' | 'child' | 'item';
    }
    /**
     * The `PathKind` for a `FieldPath` that is a child of another `FieldPath`.
     */
    interface Child extends PathKind.Root {
        [ɵɵTYPE]: 'child' | 'item';
    }
    /**
     * The `PathKind` for a `FieldPath` that is an item in a `FieldPath` array.
     */
    interface Item extends PathKind.Child {
        [ɵɵTYPE]: 'item';
    }
}
/**
 * A reason for a field's disablement.
 *
 * @category logic
 * @experimental 21.0.0
 */
interface DisabledReason {
    /** The field that is disabled. */
    readonly fieldTree: FieldTree<unknown>;
    /** A user-facing message describing the reason for the disablement. */
    readonly message?: string;
}
/**
 * The absence of an error which indicates a successful validation result.
 *
 * @category types
 * @experimental 21.0.0
 */
type ValidationSuccess = null | undefined | void;
/**
 * The result of running a tree validation function.
 *
 * The result may be one of the following:
 * 1. A {@link ValidationSuccess} to indicate no errors.
 * 2. A {@link ValidationError} without a field to indicate an error on the field being validated.
 * 3. A {@link ValidationError} with a field to indicate an error on the target field.
 * 4. A list of {@link ValidationError} with or without fields to indicate multiple errors.
 *
 * @template E the type of error (defaults to {@link ValidationError}).
 *
 * @category types
 * @experimental 21.0.0
 */
type TreeValidationResult<E extends ValidationError.WithOptionalField = ValidationError.WithOptionalField> = ValidationSuccess | OneOrMany<E>;
/**
 * A validation result where all errors explicitly define their target field.
 *
 * The result may be one of the following:
 * 1. A {@link ValidationSuccess} to indicate no errors.
 * 2. A {@link ValidationError} with a field to indicate an error on the target field.
 * 3. A list of {@link ValidationError} with fields to indicate multiple errors.
 *
 * @template E the type of error (defaults to {@link ValidationError}).
 *
 * @category types
 * @experimental 21.0.0
 */
type ValidationResult<E extends ValidationError = ValidationError> = ValidationSuccess | OneOrMany<E>;
/**
 * An asynchronous validation result where all errors explicitly define their target field.
 *
 * The result may be one of the following:
 * 1. A {@link ValidationResult} to indicate the result if resolved.
 * 5. 'pending' if the validation is not yet resolved.
 *
 * @template E the type of error (defaults to {@link ValidationError}).
 *
 * @category types
 * @experimental 21.0.0
 */
type AsyncValidationResult<E extends ValidationError = ValidationError> = ValidationResult<E> | 'pending';
/**
 * An object that represents a tree of fields in a form. This includes both primitive value fields
 * (e.g. fields that contain a `string` or `number`), as well as "grouping fields" that contain
 * sub-fields. `FieldTree` objects are arranged in a tree whose structure mimics the structure of the
 * underlying data. For example a `FieldTree<{x: number}>` has a property `x` which contains a
 * `FieldTree<number>`. To access the state associated with a field, call it as a function.
 *
 * @template TValue The type of the data which the field is wrapped around.
 * @template TKey The type of the property key which this field resides under in its parent.
 *
 * @category types
 * @experimental 21.0.0
 */
type FieldTree<TModel, TKey extends string | number = string | number> = (() => [TModel] extends [AbstractControl] ? CompatFieldState<TModel, TKey> : FieldState<TModel, TKey>) & ([TModel] extends [AbstractControl] ? object : [TModel] extends [ReadonlyArray<infer U>] ? ReadonlyArrayLike<MaybeFieldTree<U, number>> : TModel extends Record<string, any> ? Subfields<TModel> : object);
/**
 * The sub-fields that a user can navigate to from a `FieldTree<TModel>`.
 *
 * @template TModel The type of the data which the parent field is wrapped around.
 *
 * @experimental 21.0.0
 */
type Subfields<TModel> = {
    readonly [K in keyof TModel as TModel[K] extends Function ? never : K]: MaybeFieldTree<TModel[K], string>;
} & {
    [Symbol.iterator](): Iterator<[string, MaybeFieldTree<TModel[keyof TModel], string>]>;
};
/**
 * An iterable object with the same shape as a readonly array.
 *
 * @template T The array item type.
 *
 * @experimental 21.0.0
 */
type ReadonlyArrayLike<T> = Pick<ReadonlyArray<T>, number | 'length' | typeof Symbol.iterator>;
/**
 * Helper type for defining `FieldTree`. Given a type `TValue` that may include `undefined`, it extracts
 * the `undefined` outside the `FieldTree` type.
 *
 * For example `MaybeField<{a: number} | undefined, TKey>` would be equivalent to
 * `undefined | FieldTree<{a: number}, TKey>`.
 *
 * @template TModel The type of the data which the field is wrapped around.
 * @template TKey The type of the property key which this field resides under in its parent.
 *
 * @experimental 21.0.0
 */
type MaybeFieldTree<TModel, TKey extends string | number = string | number> = (TModel & undefined) | FieldTree<Exclude<TModel, undefined>, TKey>;
/**
 * Contains all of the state (e.g. value, statuses, etc.) associated with a `FieldTree`, exposed as
 * signals.
 *
 * @category structure
 * @experimental 21.0.0
 */
interface FieldState<TValue, TKey extends string | number = string | number> extends _FieldState<TValue> {
    /**
     * A signal indicating whether field value has been changed by user.
     */
    readonly dirty: Signal<boolean>;
    /**
     * A signal indicating whether a field is hidden.
     *
     * When a field is hidden it is ignored when determining the valid, touched, and dirty states.
     *
     * Note: This doesn't hide the field in the template, that must be done manually.
     * ```
     * @if (!field.hidden()) {
     *   ...
     * }
     * ```
     */
    readonly hidden: Signal<boolean>;
    readonly disabledReasons: Signal<readonly DisabledReason[]>;
    readonly errors: Signal<ValidationError.WithField[]>;
    /**
     * A signal containing the {@link errors} of the field and its descendants.
     */
    readonly errorSummary: Signal<ValidationError.WithField[]>;
    /**
     * A signal indicating whether the field's value is currently valid.
     *
     * Note: `valid()` is not the same as `!invalid()`.
     * - `valid()` is `true` when there are no validation errors *and* no pending validators.
     * - `invalid()` is `true` when there are validation errors, regardless of pending validators.
     *
     * Ex: consider the situation where a field has 3 validators, 2 of which have no errors and 1 of
     * which is still pending. In this case `valid()` is `false` because of the pending validator.
     * However `invalid()` is also `false` because there are no errors.
     */
    readonly valid: Signal<boolean>;
    /**
     * A signal indicating whether the field's value is currently invalid.
     *
     * Note: `invalid()` is not the same as `!valid()`.
     * - `invalid()` is `true` when there are validation errors, regardless of pending validators.
     * - `valid()` is `true` when there are no validation errors *and* no pending validators.
     *
     * Ex: consider the situation where a field has 3 validators, 2 of which have no errors and 1 of
     * which is still pending. In this case `invalid()` is `false` because there are no errors.
     * However `valid()` is also `false` because of the pending validator.
     */
    readonly invalid: Signal<boolean>;
    /**
     * Whether there are any validators still pending for this field.
     */
    readonly pending: Signal<boolean>;
    /**
     * A signal indicating whether the field is currently in the process of being submitted.
     */
    readonly submitting: Signal<boolean>;
    /**
     * The property key in the parent field under which this field is stored. If the parent field is
     * array-valued, for example, this is the index of this field in that array.
     */
    readonly keyInParent: Signal<TKey>;
    /**
     * The {@link FormField} directives that bind this field to a UI control.
     */
    readonly formFieldBindings: Signal<readonly FormField<unknown>[]>;
    /**
     * Reads a metadata value from the field.
     * @param key The metadata key to read.
     */
    metadata<M>(key: MetadataKey<M, any, any>): M | undefined;
    /**
     * Resets the {@link touched} and {@link dirty} state of the field and its descendants.
     *
     * Note this does not change the data model, which can be reset directly if desired.
     *
     * @param value Optional value to set to the form. If not passed, the value will not be changed.
     */
    reset(value?: TValue): void;
    /**
     * Focuses the first UI control in the DOM that is bound to this field state.
     * If no UI control is bound, does nothing.
     */
    focusBoundControl(): void;
}
/**
 * This is FieldState also providing access to the wrapped FormControl.
 *
 * @category interop
 * @experimental 21.0.0
 */
type CompatFieldState<TControl extends AbstractControl, TKey extends string | number = string | number> = FieldState<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, TKey> & {
    control: Signal<TControl>;
};
/**
 * Allows declaring whether the Rules are supported for a given path.
 *
 * @experimental 21.0.0
 **/
type SchemaPathRules = SchemaPathRules.Supported | SchemaPathRules.Unsupported;
declare namespace SchemaPathRules {
    /**
     * Used for paths that support settings rules.
     */
    type Supported = 1;
    /**
     * Used for paths that do not support settings rules, e.g., compatPath.
     */
    type Unsupported = 2;
}
/**
 * An object that represents a location in the `FieldTree` tree structure and is used to bind logic to a
 * particular part of the structure prior to the creation of the form. Because the `FieldPath`
 * exists prior to the form's creation, it cannot be used to access any of the field state.
 *
 * @template TValue The type of the data which the form is wrapped around.
 * @template TPathKind The kind of path (root field, child field, or item of an array)
 *
 * @category types
 * @experimental 21.0.0
 */
type SchemaPath<TValue, TSupportsRules extends SchemaPathRules = SchemaPathRules.Supported, TPathKind extends PathKind = PathKind.Root> = {
    [ɵɵTYPE]: {
        value: () => TValue;
        supportsRules: TSupportsRules;
        pathKind: TPathKind;
    };
};
/**
 * Schema path used if the value is an AbstractControl.
 *
 * @category interop
 * @experimental 21.0.0
 */
type CompatSchemaPath<TControl extends AbstractControl, TPathKind extends PathKind = PathKind.Root> = SchemaPath<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, SchemaPathRules.Unsupported, TPathKind> & {
    [ɵɵTYPE]: {
        control: TControl;
    };
};
/**
 * Nested schema path.
 *
 * It mirrors the structure of a given data structure, and allows applying rules to the appropriate
 * fields.
 *
 * @experimental 21.0.0
 */
type SchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = ([TModel] extends [AbstractControl] ? CompatSchemaPath<TModel, TPathKind> : SchemaPath<TModel, SchemaPathRules.Supported, TPathKind>) & (TModel extends AbstractControl ? unknown : TModel extends ReadonlyArray<any> ? unknown : TModel extends Record<string, any> ? {
    [K in keyof TModel]: MaybeSchemaPathTree<TModel[K], PathKind.Child>;
} : unknown);
/**
 * Helper type for defining `FieldPath`. Given a type `TValue` that may include `undefined`, it
 * extracts the `undefined` outside the `FieldPath` type.
 *
 * For example `MaybeFieldPath<{a: number} | undefined, PathKind.Child>` would be equivalent to
 * `undefined | FieldTree<{a: number}, PathKind.child>`.
 *
 * @template TValue The type of the data which the field is wrapped around.
 * @template TPathKind The kind of path (root field, child field, or item of an array)
 *
 * @experimental 21.0.0
 */
type MaybeSchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = (TModel & undefined) | SchemaPathTree<Exclude<TModel, undefined>, TPathKind>;
/**
 * A reusable schema that defines behavior and rules for a form.
 *
 * A `Schema` encapsulates form logic such as validation rules, disabled states, readonly states,
 * and other field-level behaviors.
 *
 * Unlike raw {@link SchemaFn}, a `Schema` is created using
 * the {@link schema} function and is cached per-form, even when applied to multiple fields.
 *
 * ### Creating a reusable schema
 *
 * ```typescript
 * interface Address {
 *   street: string;
 *   city: string;
 * }
 *
 * // Create a reusable schema for address fields
 * const addressSchema = schema<Address>((p) => {
 *   required(p.street);
 *   required(p.city);
 * });
 *
 * // Apply the schema to multiple forms
 * const shippingForm = form(shippingModel, addressSchema, {injector});
 * const billingForm = form(billingModel, addressSchema, {injector});
 * ```
 *
 * ### Passing a schema to a form
 *
 * A schema can also be passed as a second argument to the {@link form} function.
 *
 * ```typescript
 * readonly userForm = form(addressModel, addressSchema);
 * ```
 *
 * @template TModel Data type.
 *
 * @category types
 * @experimental 21.0.0
 */
type Schema<in TModel> = {
    [ɵɵTYPE]: SchemaFn<TModel, PathKind.Root>;
};
/**
 * A function that receives a {@link SchemaPathTree} and applies rules to fields.
 *
 * A `SchemaFn` can be passed directly to {@link form} or to the {@link schema} function to create a
 * cached {@link Schema}.
 *
 * ```typescript
 * const userFormSchema: SchemaFn<User> = (p) => {
 *   required(p.name);
 *   disabled(p.email, ({valueOf}) => valueOf(p.name) === '');
 * };
 *
 * const f = form(userModel, userFormSchema, {injector});
 * ```
 *
 * @template TModel Data type.
 * @template TPathKind The kind of path this schema function can be bound to.
 *
 * @category types
 * @experimental 21.0.0
 */
type SchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = (p: SchemaPathTree<TModel, TPathKind>) => void;
/**
 * A {@link Schema} or {@link SchemaFn}.
 *
 * @template TModel The type of data stored in the form that this schema function is attached to.
 * @template TPathKind The kind of path this schema function can be bound to.
 *
 * @category types
 * @experimental 21.0.0
 */
type SchemaOrSchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = Schema<TModel> | SchemaFn<TModel, TPathKind>;
/**
 * A function that receives the `FieldContext` for the field the logic is bound to and returns
 * a specific result type.
 *
 * @template TValue The data type for the field the logic is bound to.
 * @template TReturn The type of the result returned by the logic function.
 * @template TPathKind The kind of path the logic is applied to (root field, child field, or item of an array)
 *
 * @category types
 * @experimental 21.0.0
 */
type LogicFn<TValue, TReturn, TPathKind extends PathKind = PathKind.Root> = (ctx: FieldContext<TValue, TPathKind>) => TReturn;
/**
 * A function that takes the `FieldContext` for the field being validated and returns a
 * `ValidationResult` indicating errors for the field.
 *
 * @template TValue The type of value stored in the field being validated
 * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
 *
 * @category validation
 * @experimental 21.0.0
 */
type FieldValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult<ValidationError.WithoutField>, TPathKind>;
/**
 * A function that takes the `FieldContext` for the field being validated and returns a
 * `TreeValidationResult` indicating errors for the field and its sub-fields.
 *
 * @template TValue The type of value stored in the field being validated
 * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
 *
 * @category types
 * @experimental 21.0.0
 */
type TreeValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, TreeValidationResult, TPathKind>;
/**
 * A function that takes the `FieldContext` for the field being validated and returns a
 * `ValidationResult` indicating errors for the field and its sub-fields. In a `Validator` all
 * errors must explicitly define their target field.
 *
 * @template TValue The type of value stored in the field being validated
 * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
 * @see [Signal Form Validation](/guide/forms/signals/validation)
 * @category types
 * @experimental 21.0.0
 */
type Validator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult, TPathKind>;
/**
 * Provides access to the state of the current field as well as functions that can be used to look
 * up state of other fields based on a `FieldPath`.
 *
 * @category types
 * @experimental 21.0.0
 */
type FieldContext<TValue, TPathKind extends PathKind = PathKind.Root> = TPathKind extends PathKind.Item ? ItemFieldContext<TValue> : TPathKind extends PathKind.Child ? ChildFieldContext<TValue> : RootFieldContext<TValue>;
/**
 * The base field context that is available for all fields.
 *
 * @experimental 21.0.0
 */
interface RootFieldContext<TValue> {
    /** A signal containing the value of the current field. */
    readonly value: Signal<TValue>;
    /** The state of the current field. */
    readonly state: FieldState<TValue>;
    /** The current field. */
    readonly fieldTree: FieldTree<TValue>;
    /** Gets the value of the field represented by the given path. */
    valueOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): PValue;
    /** Gets the state of the field represented by the given path. */
    stateOf<PControl extends AbstractControl>(p: CompatSchemaPath<PControl>): CompatFieldState<PControl>;
    stateOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): FieldState<PValue>;
    /** Gets the field represented by the given path. */
    fieldTreeOf<PModel>(p: SchemaPathTree<PModel>): FieldTree<PModel>;
    /** The list of keys that lead from the root field to the current field. */
    readonly pathKeys: Signal<readonly string[]>;
}
/**
 * Field context that is available for all fields that are a child of another field.
 *
 * @category structure
 * @experimental 21.0.0
 */
interface ChildFieldContext<TValue> extends RootFieldContext<TValue> {
    /** The key of the current field in its parent field. */
    readonly key: Signal<string>;
}
/**
 * Field context that is available for all fields that are an item in an array field.
 *
 * @experimental 21.0.0
 */
interface ItemFieldContext<TValue> extends ChildFieldContext<TValue> {
    /** The index of the current field in its parent field. */
    readonly index: Signal<number>;
}
/**
 * Gets the item type of an object that is possibly an array.
 *
 * @experimental 21.0.0
 */
type ItemType<T extends Object> = T extends ReadonlyArray<any> ? T[number] : T[keyof T];
/**
 * A function that defines custom debounce logic for a field.
 *
 * @param context The field context.
 * @param abortSignal An `AbortSignal` used to communicate that the debounced operation was aborted.
 * @returns A `Promise<void>` to debounce an update, or `void` to apply an update immediately.
 * @template TValue The type of value stored in the field.
 * @template TPathKind The kind of path the debouncer is applied to (root field, child field, or item of an array).
 *
 * @experimental 21.0.0
 */
type Debouncer<TValue, TPathKind extends PathKind = PathKind.Root> = (context: FieldContext<TValue, TPathKind>, abortSignal: AbortSignal) => Promise<void> | void;

/**
 * Options used to create a `ValidationError`.
 */
interface ValidationErrorOptions {
    /** Human readable error message. */
    message?: string;
}
/**
 * A type that requires the given type `T` to have a `field` property.
 * @template T The type to add a `field` to.
 *
 * @experimental 21.0.0
 */
type WithField<T> = T & {
    fieldTree: FieldTree<unknown>;
};
/**
 * A type that allows the given type `T` to optionally have a `field` property.
 * @template T The type to optionally add a `field` to.
 *
 * @experimental 21.0.0
 */
type WithOptionalField<T> = Omit<T, 'fieldTree'> & {
    fieldTree?: FieldTree<unknown>;
};
/**
 * A type that ensures the given type `T` does not have a `field` property.
 * @template T The type to remove the `field` from.
 *
 * @experimental 21.0.0
 */
type WithoutField<T> = T & {
    fieldTree: never;
};
/**
 * Create a required error associated with the target field
 * @param options The validation error options
 *
 * @experimental 21.0.0
 */
declare function requiredError(options: WithField<ValidationErrorOptions>): RequiredValidationError;
/**
 * Create a required error
 * @param options The optional validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function requiredError(options?: ValidationErrorOptions): WithoutField<RequiredValidationError>;
/**
 * Create a min value error associated with the target field
 * @param min The min value constraint
 * @param options The validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function minError(min: number, options: WithField<ValidationErrorOptions>): MinValidationError;
/**
 * Create a min value error
 * @param min The min value constraint
 * @param options The optional validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function minError(min: number, options?: ValidationErrorOptions): WithoutField<MinValidationError>;
/**
 * Create a max value error associated with the target field
 * @param max The max value constraint
 * @param options The validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function maxError(max: number, options: WithField<ValidationErrorOptions>): MaxValidationError;
/**
 * Create a max value error
 * @param max The max value constraint
 * @param options The optional validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function maxError(max: number, options?: ValidationErrorOptions): WithoutField<MaxValidationError>;
/**
 * Create a minLength error associated with the target field
 * @param minLength The minLength constraint
 * @param options The validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function minLengthError(minLength: number, options: WithField<ValidationErrorOptions>): MinLengthValidationError;
/**
 * Create a minLength error
 * @param minLength The minLength constraint
 * @param options The optional validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function minLengthError(minLength: number, options?: ValidationErrorOptions): WithoutField<MinLengthValidationError>;
/**
 * Create a maxLength error associated with the target field
 * @param maxLength The maxLength constraint
 * @param options The validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function maxLengthError(maxLength: number, options: WithField<ValidationErrorOptions>): MaxLengthValidationError;
/**
 * Create a maxLength error
 * @param maxLength The maxLength constraint
 * @param options The optional validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function maxLengthError(maxLength: number, options?: ValidationErrorOptions): WithoutField<MaxLengthValidationError>;
/**
 * Create a pattern matching error associated with the target field
 * @param pattern The violated pattern
 * @param options The validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function patternError(pattern: RegExp, options: WithField<ValidationErrorOptions>): PatternValidationError;
/**
 * Create a pattern matching error
 * @param pattern The violated pattern
 * @param options The optional validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function patternError(pattern: RegExp, options?: ValidationErrorOptions): WithoutField<PatternValidationError>;
/**
 * Create an email format error associated with the target field
 * @param options The validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function emailError(options: WithField<ValidationErrorOptions>): EmailValidationError;
/**
 * Create an email format error
 * @param options The optional validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function emailError(options?: ValidationErrorOptions): WithoutField<EmailValidationError>;
/**
 * Create a standard schema issue error associated with the target field
 * @param issue The standard schema issue
 * @param options The validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function standardSchemaError(issue: StandardSchemaV1.Issue, options: WithField<ValidationErrorOptions>): StandardSchemaValidationError;
/**
 * Create a standard schema issue error
 * @param issue The standard schema issue
 * @param options The optional validation error options
 *
 * @category validation
 * @experimental 21.0.0
 */
declare function standardSchemaError(issue: StandardSchemaV1.Issue, options?: ValidationErrorOptions): WithoutField<StandardSchemaValidationError>;
/**
 * Common interface for all validation errors.
 *
 * This can be returned from validators.
 *
 * It's also used by the creation functions to create an instance
 * (e.g. `requiredError`, `minError`, etc.).
 *
 * @see [Signal Form Validation](guide/forms/signals/validation)
 * @see [Signal Form Validation Errors](guide/forms/signals/validation#validation-errors)
 * @category validation
 * @experimental 21.0.0
 */
interface ValidationError {
    /** Identifies the kind of error. */
    readonly kind: string;
    /** Human readable error message. */
    readonly message?: string;
}
declare namespace ValidationError {
    /**
     * Validation error with a field.
     *
     * This is returned from field state, e.g., catField.errors() would be of a list of errors with
     * `field: catField` bound to state.
     */
    interface WithField extends ValidationError {
        /** The field associated with this error. */
        readonly fieldTree: FieldTree<unknown>;
    }
    /**
     * Validation error with optional field.
     *
     * This is generally used in places where the result might have a field.
     * e.g., as a result of a `validateTree`, or when handling form submission.
     */
    interface WithOptionalField extends ValidationError {
        /** The field associated with this error. */
        readonly fieldTree?: FieldTree<unknown>;
    }
    /**
     * Validation error with no field.
     *
     * This is used to strongly enforce that fields are not allowed in validation result.
     */
    interface WithoutField extends ValidationError {
        /** The field associated with this error. */
        readonly fieldTree?: never;
    }
}
/**
 * Internal version of `NgValidationError`, we create this separately so we can change its type on
 * the exported version to a type union of the possible sub-classes.
 *
 * @experimental 21.0.0
 */
declare abstract class _NgValidationError implements ValidationError {
    /** Brand the class to avoid Typescript structural matching */
    private __brand;
    /** Identifies the kind of error. */
    readonly kind: string;
    /** The field associated with this error. */
    readonly fieldTree: FieldTree<unknown>;
    /** Human readable error message. */
    readonly message?: string;
    constructor(options?: ValidationErrorOptions);
}
/**
 * An error used to indicate that a required field is empty.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare class RequiredValidationError extends _NgValidationError {
    readonly kind = "required";
}
/**
 * An error used to indicate that a value is lower than the minimum allowed.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare class MinValidationError extends _NgValidationError {
    readonly min: number;
    readonly kind = "min";
    constructor(min: number, options?: ValidationErrorOptions);
}
/**
 * An error used to indicate that a value is higher than the maximum allowed.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare class MaxValidationError extends _NgValidationError {
    readonly max: number;
    readonly kind = "max";
    constructor(max: number, options?: ValidationErrorOptions);
}
/**
 * An error used to indicate that a value is shorter than the minimum allowed length.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare class MinLengthValidationError extends _NgValidationError {
    readonly minLength: number;
    readonly kind = "minLength";
    constructor(minLength: number, options?: ValidationErrorOptions);
}
/**
 * An error used to indicate that a value is longer than the maximum allowed length.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare class MaxLengthValidationError extends _NgValidationError {
    readonly maxLength: number;
    readonly kind = "maxLength";
    constructor(maxLength: number, options?: ValidationErrorOptions);
}
/**
 * An error used to indicate that a value does not match the required pattern.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare class PatternValidationError extends _NgValidationError {
    readonly pattern: RegExp;
    readonly kind = "pattern";
    constructor(pattern: RegExp, options?: ValidationErrorOptions);
}
/**
 * An error used to indicate that a value is not a valid email.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare class EmailValidationError extends _NgValidationError {
    readonly kind = "email";
}
/**
 * An error used to indicate an issue validating against a standard schema.
 *
 * @category validation
 * @experimental 21.0.0
 */
declare class StandardSchemaValidationError extends _NgValidationError {
    readonly issue: StandardSchemaV1.Issue;
    readonly kind = "standardSchema";
    constructor(issue: StandardSchemaV1.Issue, options?: ValidationErrorOptions);
}
/**
 * The base class for all built-in, non-custom errors. This class can be used to check if an error
 * is one of the standard kinds, allowing you to switch on the kind to further narrow the type.
 *
 * @example
 * ```ts
 * const f = form(...);
 * for (const e of form().errors()) {
 *   if (e instanceof NgValidationError) {
 *     switch(e.kind) {
 *       case 'required':
 *         console.log('This is required!');
 *         break;
 *       case 'min':
 *         console.log(`Must be at least ${e.min}`);
 *         break;
 *       ...
 *     }
 *   }
 * }
 * ```
 *
 * @category validation
 * @experimental 21.0.0
 */
declare const NgValidationError: abstract new () => NgValidationError;
type NgValidationError = RequiredValidationError | MinValidationError | MaxValidationError | MinLengthValidationError | MaxLengthValidationError | PatternValidationError | EmailValidationError | StandardSchemaValidationError;

/**
 * Configuration options for signal forms.
 *
 * @experimental 21.0.1
 */
interface SignalFormsConfig {
    /** A map of CSS class names to predicate functions that determine when to apply them. */
    classes?: {
        [className: string]: (state: FormField<unknown>) => boolean;
    };
}
/**
 * Provides configuration options for signal forms.
 *
 * @experimental 21.0.1
 */
declare function provideSignalFormsConfig(config: SignalFormsConfig): Provider[];

/** Represents a result that should be ignored because its predicate indicates it is not active. */
declare const IGNORED: unique symbol;
/**
 * A predicate that indicates whether an `AbstractLogic` instance is currently active, or should be
 * ignored.
 */
interface Predicate {
    /** A boolean logic function that returns true if the logic is considered active. */
    readonly fn: LogicFn<any, boolean>;
    /**
     * The path which this predicate was created for. This is used to determine the correct
     * `FieldContext` to pass to the predicate function.
     */
    readonly path: SchemaPath<any>;
}
/**
 * Represents a predicate that is bound to a particular depth in the field tree. This is needed for
 * recursively applied logic to ensure that the predicate is evaluated against the correct
 * application of that logic.
 *
 * Consider the following example:
 *
 * ```ts
 * const s = schema(p => {
 *   disabled(p.data);
 *   applyWhen(p.next, ({valueOf}) => valueOf(p.data) === 1, s);
 * });
 *
 * const f = form(signal({data: 0, next: {data: 1, next: {data: 2, next: undefined}}}), s);
 *
 * const isDisabled = f.next.next.data().disabled();
 * ```
 *
 * In order to determine `isDisabled` we need to evaluate the predicate from `applyWhen` *twice*.
 * Once to see if the schema should be applied to `f.next` and again to see if it should be applied
 * to `f.next.next`. The `depth` tells us which field we should be evaluating against each time.
 */
interface BoundPredicate extends Predicate {
    /** The depth in the field tree at which this predicate is bound. */
    readonly depth: number;
}
/**
 * Base class for all logic. It is responsible for combining the results from multiple individual
 * logic functions registered in the schema, and using them to derive the value for some associated
 * piece of field state.
 */
declare abstract class AbstractLogic<TReturn, TValue = TReturn> {
    /**
     * A list of predicates that conditionally enable all logic in this logic instance.
     * The logic is only enabled when *all* of the predicates evaluate to true.
     */
    private predicates;
    /** The set of logic functions that contribute to the value of the associated state. */
    protected readonly fns: Array<LogicFn<any, TValue | typeof IGNORED>>;
    constructor(
    /**
     * A list of predicates that conditionally enable all logic in this logic instance.
     * The logic is only enabled when *all* of the predicates evaluate to true.
     */
    predicates: ReadonlyArray<BoundPredicate>);
    /**
     * Computes the value of the associated field state based on the logic functions and predicates
     * registered with this logic instance.
     */
    abstract compute(arg: FieldContext<any>): TReturn;
    /**
     * The default value that the associated field state should assume if there are no logic functions
     * registered by the schema (or if the logic is disabled by a predicate).
     */
    abstract get defaultValue(): TReturn;
    /** Registers a logic function with this logic instance. */
    push(logicFn: LogicFn<any, TValue>): void;
    /**
     * Merges in the logic from another logic instance, subject to the predicates of both the other
     * instance and this instance.
     */
    mergeIn(other: AbstractLogic<TReturn, TValue>): void;
}
/** Logic that combines its individual logic function results with logical OR. */
declare class BooleanOrLogic extends AbstractLogic<boolean> {
    get defaultValue(): boolean;
    compute(arg: FieldContext<any>): boolean;
}
/**
 * Logic that combines its individual logic function results by aggregating them in an array.
 * Depending on its `ignore` function it may ignore certain values, omitting them from the array.
 */
declare class ArrayMergeIgnoreLogic<TElement, TIgnore = never> extends AbstractLogic<readonly TElement[], TElement | readonly (TElement | TIgnore)[] | TIgnore | undefined | void> {
    private ignore;
    /** Creates an instance of this class that ignores `null` values. */
    static ignoreNull<TElement>(predicates: ReadonlyArray<BoundPredicate>): ArrayMergeIgnoreLogic<TElement, null>;
    constructor(predicates: ReadonlyArray<BoundPredicate>, ignore: undefined | ((e: TElement | undefined | TIgnore) => e is TIgnore));
    get defaultValue(): never[];
    compute(arg: FieldContext<any>): readonly TElement[];
}
/** Logic that combines its individual logic function results by aggregating them in an array. */
declare class ArrayMergeLogic<TElement> extends ArrayMergeIgnoreLogic<TElement, never> {
    constructor(predicates: ReadonlyArray<BoundPredicate>);
}
/**
 * Container for all the different types of logic that can be applied to a field
 * (disabled, hidden, errors, etc.)
 */
declare class LogicContainer {
    private predicates;
    /** Logic that determines if the field is hidden. */
    readonly hidden: BooleanOrLogic;
    /** Logic that determines reasons for the field being disabled. */
    readonly disabledReasons: ArrayMergeLogic<DisabledReason>;
    /** Logic that determines if the field is read-only. */
    readonly readonly: BooleanOrLogic;
    /** Logic that produces synchronous validation errors for the field. */
    readonly syncErrors: ArrayMergeIgnoreLogic<ValidationError.WithField, null>;
    /** Logic that produces synchronous validation errors for the field's subtree. */
    readonly syncTreeErrors: ArrayMergeIgnoreLogic<ValidationError.WithField, null>;
    /** Logic that produces asynchronous validation results (errors or 'pending'). */
    readonly asyncErrors: ArrayMergeIgnoreLogic<ValidationError.WithField | 'pending', null>;
    /** A map of metadata keys to the `AbstractLogic` instances that compute their values. */
    private readonly metadata;
    /**
     * Constructs a new `Logic` container.
     * @param predicates An array of predicates that must all be true for the logic
     *   functions within this container to be active.
     */
    constructor(predicates: ReadonlyArray<BoundPredicate>);
    /** Checks whether there is logic for the given metadata key. */
    hasMetadata(key: MetadataKey<any, any, any>): boolean;
    /**
     * Gets an iterable of [metadata key, logic function] pairs.
     * @returns An iterable of metadata keys.
     */
    getMetadataKeys(): MapIterator<MetadataKey<unknown, unknown, unknown>>;
    /**
     * Retrieves or creates the `AbstractLogic` for a given metadata key.
     * @param key The `MetadataKey` for which to get the logic.
     * @returns The `AbstractLogic` associated with the key.
     */
    getMetadata<T>(key: MetadataKey<any, T, any>): AbstractLogic<T>;
    /**
     * Merges logic from another `Logic` instance into this one.
     * @param other The `Logic` instance to merge from.
     */
    mergeIn(other: LogicContainer): void;
}

/**
 * Abstract base class for building a `LogicNode`.
 * This class defines the interface for adding various logic rules (e.g., hidden, disabled)
 * and data factories to a node in the logic tree.
 * LogicNodeBuilders are 1:1 with nodes in the Schema tree.
 */
declare abstract class AbstractLogicNodeBuilder {
    /** The depth of this node in the schema tree. */
    protected readonly depth: number;
    constructor(
    /** The depth of this node in the schema tree. */
    depth: number);
    /** Adds a rule to determine if a field should be hidden. */
    abstract addHiddenRule(logic: LogicFn<any, boolean>): void;
    /** Adds a rule to determine if a field should be disabled, and for what reason. */
    abstract addDisabledReasonRule(logic: LogicFn<any, DisabledReason | undefined>): void;
    /** Adds a rule to determine if a field should be read-only. */
    abstract addReadonlyRule(logic: LogicFn<any, boolean>): void;
    /** Adds a rule for synchronous validation errors for a field. */
    abstract addSyncErrorRule(logic: LogicFn<any, ValidationResult>): void;
    /** Adds a rule for synchronous validation errors that apply to a subtree. */
    abstract addSyncTreeErrorRule(logic: LogicFn<any, ValidationResult>): void;
    /** Adds a rule for asynchronous validation errors for a field. */
    abstract addAsyncErrorRule(logic: LogicFn<any, AsyncValidationResult>): void;
    /** Adds a rule to compute metadata for a field. */
    abstract addMetadataRule<M>(key: MetadataKey<unknown, M, unknown>, logic: LogicFn<any, M>): void;
    /**
     * Gets a builder for a child node associated with the given property key.
     * @param key The property key of the child.
     * @returns A `LogicNodeBuilder` for the child.
     */
    abstract getChild(key: PropertyKey): LogicNodeBuilder;
    /**
     * Checks whether a particular `AbstractLogicNodeBuilder` has been merged into this one.
     * @param builder The builder to check for.
     * @returns True if the builder has been merged, false otherwise.
     */
    abstract hasLogic(builder: AbstractLogicNodeBuilder): boolean;
    /**
     * Builds the `LogicNode` from the accumulated rules and child builders.
     * @returns The constructed `LogicNode`.
     */
    build(): LogicNode;
}
/**
 * A builder for `LogicNode`. Used to add logic to the final `LogicNode` tree.
 * This builder supports merging multiple sources of logic, potentially with predicates,
 * preserving the order of rule application.
 */
declare class LogicNodeBuilder extends AbstractLogicNodeBuilder {
    constructor(depth: number);
    /**
     * The current `NonMergeableLogicNodeBuilder` being used to add rules directly to this
     * `LogicNodeBuilder`. Do not use this directly, call `getCurrent()` which will create a current
     * builder if there is none.
     */
    private current;
    /**
     * Stores all builders that contribute to this node, along with any predicates
     * that gate their application.
     */
    readonly all: {
        builder: AbstractLogicNodeBuilder;
        predicate?: Predicate;
    }[];
    addHiddenRule(logic: LogicFn<any, boolean>): void;
    addDisabledReasonRule(logic: LogicFn<any, DisabledReason | undefined>): void;
    addReadonlyRule(logic: LogicFn<any, boolean>): void;
    addSyncErrorRule(logic: LogicFn<any, ValidationResult<ValidationError.WithField>>): void;
    addSyncTreeErrorRule(logic: LogicFn<any, ValidationResult<ValidationError.WithField>>): void;
    addAsyncErrorRule(logic: LogicFn<any, AsyncValidationResult<ValidationError.WithField>>): void;
    addMetadataRule<T>(key: MetadataKey<unknown, T, any>, logic: LogicFn<any, T>): void;
    getChild(key: PropertyKey): LogicNodeBuilder;
    hasLogic(builder: AbstractLogicNodeBuilder): boolean;
    /**
     * Merges logic from another `LogicNodeBuilder` into this one.
     * If a `predicate` is provided, all logic from the `other` builder will only apply
     * when the predicate evaluates to true.
     * @param other The `LogicNodeBuilder` to merge in.
     * @param predicate An optional predicate to gate the merged logic.
     */
    mergeIn(other: LogicNodeBuilder, predicate?: Predicate): void;
    /**
     * Gets the current `NonMergeableLogicNodeBuilder` for adding rules directly to this
     * `LogicNodeBuilder`. If no current builder exists, a new one is created.
     * The current builder is cleared whenever `mergeIn` is called to preserve the order
     * of rules when merging separate builder trees.
     * @returns The current `NonMergeableLogicNodeBuilder`.
     */
    private getCurrent;
    /**
     * Creates a new root `LogicNodeBuilder`.
     * @returns A new instance of `LogicNodeBuilder`.
     */
    static newRoot(): LogicNodeBuilder;
}
/**
 * Represents a node in the logic tree, containing all logic applicable
 * to a specific field or path in the form structure.
 * LogicNodes are 1:1 with nodes in the Field tree.
 */
interface LogicNode {
    /** The collection of logic rules (hidden, disabled, errors, etc.) for this node. */
    readonly logic: LogicContainer;
    /**
     * Retrieves the `LogicNode` for a child identified by the given property key.
     * @param key The property key of the child.
     * @returns The `LogicNode` for the specified child.
     */
    getChild(key: PropertyKey): LogicNode;
    /**
     * Checks whether the logic from a particular `AbstractLogicNodeBuilder` has been merged into this
     * node.
     * @param builder The builder to check for.
     * @returns True if the builder has been merged, false otherwise.
     */
    hasLogic(builder: AbstractLogicNodeBuilder): boolean;
}

/**
 * Implements the `Schema` concept.
 */
declare class SchemaImpl {
    private schemaFn;
    constructor(schemaFn: SchemaFn<unknown>);
    /**
     * Compiles this schema within the current root compilation context. If the schema was previously
     * compiled within this context, we reuse the cached FieldPathNode, otherwise we create a new one
     * and cache it in the compilation context.
     */
    compile(): FieldPathNode;
    /**
     * Creates a SchemaImpl from the given SchemaOrSchemaFn.
     */
    static create(schema: SchemaImpl | SchemaOrSchemaFn<any>): SchemaImpl;
    /**
     * Compiles the given schema in a fresh compilation context. This clears the cached results of any
     * previous compilations.
     */
    static rootCompile(schema: SchemaImpl | SchemaOrSchemaFn<any> | undefined): FieldPathNode;
}

/**
 * A path in the schema on which logic is stored so that it can be added to the corresponding field
 * when the field is created.
 */
declare class FieldPathNode {
    /** The property keys used to navigate from the root path to this path. */
    readonly keys: PropertyKey[];
    /** The parent of this path node. */
    private readonly parent;
    /** The key of this node in its parent. */
    private readonly keyInParent;
    /** The root path node from which this path node is descended. */
    readonly root: FieldPathNode;
    /**
     * A map containing all child path nodes that have been created on this path.
     * Child path nodes are created automatically on first access if they do not exist already.
     */
    private readonly children;
    /**
     * A proxy that wraps the path node, allowing navigation to its child paths via property access.
     */
    readonly fieldPathProxy: SchemaPath<any>;
    /**
     * For a root path node this will contain the root logic builder. For non-root nodes,
     * they determine their logic builder from their parent so this is undefined.
     */
    private readonly logicBuilder;
    protected constructor(
    /** The property keys used to navigate from the root path to this path. */
    keys: PropertyKey[], root: FieldPathNode | undefined, 
    /** The parent of this path node. */
    parent: FieldPathNode | undefined, 
    /** The key of this node in its parent. */
    keyInParent: PropertyKey | undefined);
    /** The logic builder used to accumulate logic on this path node. */
    get builder(): LogicNodeBuilder;
    /**
     * Gets the path node for the given child property key.
     * Child paths are created automatically on first access if they do not exist already.
     */
    getChild(key: PropertyKey): FieldPathNode;
    /**
     * Merges in logic from another schema to this one.
     * @param other The other schema to merge in the logic from
     * @param predicate A predicate indicating when the merged in logic should be active.
     */
    mergeIn(other: SchemaImpl, predicate?: Predicate): void;
    /** Extracts the underlying path node from the given path proxy. */
    static unwrapFieldPath(formPath: SchemaPath<unknown, SchemaPathRules>): FieldPathNode;
    /** Creates a new root path node to be passed in to a schema function. */
    static newRoot(): FieldPathNode;
}

/**
 * Tracks custom metadata associated with a `FieldNode`.
 */
declare class FieldMetadataState {
    private readonly node;
    /** A map of all `MetadataKey` that have been defined for this field. */
    private readonly metadata;
    constructor(node: FieldNode);
    /** Gets the value of an `MetadataKey` for the field. */
    get<T>(key: MetadataKey<T, unknown, unknown>): T | undefined;
    /** Checks whether the current metadata state has the given metadata key. */
    has(key: MetadataKey<any, any, any>): boolean;
}

/**
 * The non-validation and non-submit state associated with a `FieldNode`, such as touched and dirty
 * status, as well as derived logical state.
 */
declare class FieldNodeState {
    private readonly node;
    /**
     * Indicates whether this field has been touched directly by the user (as opposed to indirectly by
     * touching a child field).
     *
     * A field is considered directly touched when a user stops editing it for the first time (i.e. on blur)
     */
    private readonly selfTouched;
    /**
     * Indicates whether this field has been dirtied directly by the user (as opposed to indirectly by
     * dirtying a child field).
     *
     * A field is considered directly dirtied if a user changed the value of the field at least once.
     */
    private readonly selfDirty;
    /**
     * Marks this specific field as touched.
     */
    markAsTouched(): void;
    /**
     * Marks this specific field as dirty.
     */
    markAsDirty(): void;
    /**
     * Marks this specific field as not dirty.
     */
    markAsPristine(): void;
    /**
     * Marks this specific field as not touched.
     */
    markAsUntouched(): void;
    /** The {@link FormField} directives that bind this field to a UI control. */
    readonly formFieldBindings: i0.WritableSignal<readonly FormField<unknown>[]>;
    constructor(node: FieldNode);
    /**
     * Whether this field is considered dirty.
     *
     * A field is considered dirty if one of the following is true:
     *  - It was directly dirtied and is interactive
     *  - One of its children is considered dirty
     */
    readonly dirty: Signal<boolean>;
    /**
     * Whether this field is considered touched.
     *
     * A field is considered touched if one of the following is true:
     *  - It was directly touched and is interactive
     *  - One of its children is considered touched
     */
    readonly touched: Signal<boolean>;
    /**
     * The reasons for this field's disablement. This includes disabled reasons for any parent field
     * that may have been disabled, indirectly causing this field to be disabled as well.
     * The `field` property of the `DisabledReason` can be used to determine which field ultimately
     * caused the disablement.
     */
    readonly disabledReasons: Signal<readonly DisabledReason[]>;
    /**
     * Whether this field is considered disabled.
     *
     * A field is considered disabled if one of the following is true:
     * - The schema contains logic that directly disabled it
     * - Its parent field is considered disabled
     */
    readonly disabled: Signal<boolean>;
    /**
     * Whether this field is considered readonly.
     *
     * A field is considered readonly if one of the following is true:
     * - The schema contains logic that directly made it readonly
     * - Its parent field is considered readonly
     */
    readonly readonly: Signal<boolean>;
    /**
     * Whether this field is considered hidden.
     *
     * A field is considered hidden if one of the following is true:
     * - The schema contains logic that directly hides it
     * - Its parent field is considered hidden
     */
    readonly hidden: Signal<boolean>;
    readonly name: Signal<string>;
    /**
     * An optional {@link Debouncer} factory for this field.
     */
    readonly debouncer: Signal<((signal: AbortSignal) => Promise<void> | void) | undefined>;
    /** Whether this field is considered non-interactive.
     *
     * A field is considered non-interactive if one of the following is true:
     * - It is hidden
     * - It is disabled
     * - It is readonly
     */
    private readonly isNonInteractive;
}

/**
 * State of a `FieldNode` that's associated with form submission.
 */
declare class FieldSubmitState {
    private readonly node;
    /**
     * Whether this field was directly submitted (as opposed to indirectly by a parent field being submitted)
     * and is still in the process of submitting.
     */
    readonly selfSubmitting: WritableSignal<boolean>;
    /** Submission errors that are associated with this field. */
    readonly submissionErrors: WritableSignal<readonly ValidationError.WithField[]>;
    constructor(node: FieldNode);
    /**
     * Whether this form is currently in the process of being submitted.
     * Either because the field was submitted directly, or because a parent field was submitted.
     */
    readonly submitting: Signal<boolean>;
}

interface ValidationState {
    /**
     * The full set of synchronous tree errors visible to this field. This includes ones that are
     * targeted at a descendant field rather than at this field.
     */
    rawSyncTreeErrors: Signal<ValidationError.WithField[]>;
    /**
     * The full set of synchronous errors for this field, including synchronous tree errors and submission
     * errors. Submission errors are considered "synchronous" because they are imperatively added. From
     * the perspective of the field state they are either there or not, they are never in a pending
     * state.
     */
    syncErrors: Signal<ValidationError.WithField[]>;
    /**
     * Whether the field is considered valid according solely to its synchronous validators.
     * Errors resulting from a previous submit attempt are also considered for this state.
     */
    syncValid: Signal<boolean>;
    /**
     * The full set of asynchronous tree errors visible to this field. This includes ones that are
     * targeted at a descendant field rather than at this field, as well as sentinel 'pending' values
     * indicating that the validator is still running and an error could still occur.
     */
    rawAsyncErrors: Signal<(ValidationError.WithField | 'pending')[]>;
    /**
     * The asynchronous tree errors visible to this field that are specifically targeted at this field
     * rather than a descendant. This also includes all 'pending' sentinel values, since those could
     * theoretically result in errors for this field.
     */
    asyncErrors: Signal<(ValidationError.WithField | 'pending')[]>;
    /**
     * The combined set of all errors that currently apply to this field.
     */
    errors: Signal<ValidationError.WithField[]>;
    /**
     * The combined set of all errors that currently apply to this field and its descendants.
     */
    errorSummary: Signal<ValidationError.WithField[]>;
    /**
     * Whether this field has any asynchronous validators still pending.
     */
    pending: Signal<boolean>;
    /**
     * The validation status of the field.
     * - The status is 'valid' if neither the field nor any of its children has any errors or pending
     *   validators.
     * - The status is 'invalid' if the field or any of its children has an error
     *   (regardless of pending validators)
     * - The status is 'unknown' if neither the field nor any of its children has any errors,
     *   but the field or any of its children does have a pending validator.
     *
     * A field is considered valid if *all* of the following are true:
     *  - It has no errors or pending validators
     *  - All of its children are considered valid
     * A field is considered invalid if *any* of the following are true:
     *  - It has an error
     *  - Any of its children is considered invalid
     * A field is considered to have unknown validity status if it is not valid or invalid.
     */
    status: Signal<'valid' | 'invalid' | 'unknown'>;
    /**
     * Whether the field is considered valid.
     *
     * A field is considered valid if *all* of the following are true:
     *  - It has no errors or pending validators
     *  - All of its children are considered valid
     *
     * Note: `!valid()` is *not* the same as `invalid()`. Both `valid()` and `invalid()` can be false
     * if there are currently no errors, but validators are still pending.
     */
    valid: Signal<boolean>;
    /**
     * Whether the field is considered invalid.
     *
     * A field is considered invalid if *any* of the following are true:
     *  - It has an error
     *  - Any of its children is considered invalid
     *
     * Note: `!invalid()` is *not* the same as `valid()`. Both `valid()` and `invalid()` can be false
     * if there are currently no errors, but validators are still pending.
     */
    invalid: Signal<boolean>;
    /**
     * Indicates whether validation should be skipped for this field because it is hidden, disabled,
     * or readonly.
     */
    shouldSkipValidation: Signal<boolean>;
}

/**
 * Internal node in the form tree for a given field.
 *
 * Field nodes have several responsibilities:
 *  - They track instance state for the particular field (touched)
 *  - They compute signals for derived state (valid, disabled, etc) based on their associated
 *    `LogicNode`
 *  - They act as the public API for the field (they implement the `FieldState` interface)
 *  - They implement navigation of the form tree via `.parent` and `.getChild()`.
 *
 * This class is largely a wrapper that aggregates several smaller pieces that each manage a subset of
 * the responsibilities.
 */
declare class FieldNode implements FieldState<unknown> {
    readonly structure: FieldNodeStructure;
    readonly validationState: ValidationState;
    readonly metadataState: FieldMetadataState;
    readonly nodeState: FieldNodeState;
    readonly submitState: FieldSubmitState;
    readonly fieldAdapter: FieldAdapter;
    private _context;
    get context(): FieldContext<unknown>;
    /**
     * Proxy to this node which allows navigation of the form graph below it.
     */
    readonly fieldProxy: FieldTree<any>;
    private readonly pathNode;
    constructor(options: FieldNodeOptions);
    focusBoundControl(): void;
    /**
     * Gets the Field directive binding that should be focused when the developer calls
     * `focusBoundControl` on this node.
     *
     * This will prioritize focusable bindings to this node, and if multiple exist, it will return
     * the first one in the DOM. If no focusable bindings exist on this node, it will return the
     * first focusable binding in the DOM for any descendant node of this one.
     */
    private getBindingForFocus;
    /**
     * The `AbortController` for the currently debounced sync, or `undefined` if there is none.
     *
     * This is used to cancel a pending debounced sync when {@link setControlValue} is called again
     * before the pending debounced sync resolves. It will also cancel any pending debounced sync
     * automatically when recomputed due to `value` being set directly from others sources.
     */
    private readonly pendingSync;
    get logicNode(): LogicNode;
    get value(): WritableSignal<unknown>;
    private _controlValue;
    get controlValue(): Signal<unknown>;
    get keyInParent(): Signal<string | number>;
    get errors(): Signal<ValidationError.WithField[]>;
    get errorSummary(): Signal<ValidationError.WithField[]>;
    get pending(): Signal<boolean>;
    get valid(): Signal<boolean>;
    get invalid(): Signal<boolean>;
    get dirty(): Signal<boolean>;
    get touched(): Signal<boolean>;
    get disabled(): Signal<boolean>;
    get disabledReasons(): Signal<readonly DisabledReason[]>;
    get hidden(): Signal<boolean>;
    get readonly(): Signal<boolean>;
    get formFieldBindings(): Signal<readonly FormField<unknown>[]>;
    get submitting(): Signal<boolean>;
    get name(): Signal<string>;
    get max(): Signal<number | undefined> | undefined;
    get maxLength(): Signal<number | undefined> | undefined;
    get min(): Signal<number | undefined> | undefined;
    get minLength(): Signal<number | undefined> | undefined;
    get pattern(): Signal<readonly RegExp[]>;
    get required(): Signal<boolean>;
    metadata<M>(key: MetadataKey<M, any, any>): M | undefined;
    hasMetadata(key: MetadataKey<any, any, any>): boolean;
    /**
     * Marks this specific field as touched.
     */
    markAsTouched(): void;
    /**
     * Marks this specific field as dirty.
     */
    markAsDirty(): void;
    /**
     * Resets the {@link touched} and {@link dirty} state of the field and its descendants.
     *
     * Note this does not change the data model, which can be reset directly if desired.
     *
     * @param value Optional value to set to the form. If not passed, the value will not be changed.
     */
    reset(value?: unknown): void;
    private _reset;
    /**
     * Sets the control value of the field. This value may be debounced before it is synchronized with
     * the field's {@link value} signal, depending on the debounce configuration.
     */
    setControlValue(newValue: unknown): void;
    /**
     * Synchronizes the {@link controlValue} with the {@link value} signal immediately.
     */
    private sync;
    /**
     * If there is a pending sync, abort it and sync immediately.
     */
    private flushSync;
    /**
     * Initiates a debounced {@link sync}.
     *
     * If a debouncer is configured, the synchronization will occur after the debouncer resolves. If
     * no debouncer is configured, the synchronization happens immediately. If {@link setControlValue}
     * is called again while a debounce is pending, the previous debounce operation is aborted in
     * favor of the new one.
     */
    private debounceSync;
    /**
     * Creates a new root field node for a new form.
     */
    static newRoot<T>(fieldManager: FormFieldManager, value: WritableSignal<T>, pathNode: FieldPathNode, adapter: FieldAdapter): FieldNode;
    createStructure(options: FieldNodeOptions): RootFieldNodeStructure | ChildFieldNodeStructure;
    private newChild;
}
/**
 * Field node of a field that has children.
 * This simplifies and makes certain types cleaner.
 */
interface ParentFieldNode extends FieldNode {
    readonly value: WritableSignal<Record<string, unknown>>;
    readonly structure: FieldNodeStructure & {
        value: WritableSignal<Record<string, unknown>>;
    };
}

/**
 * Key by which a parent `FieldNode` tracks its children.
 *
 * Often this is the actual property key of the child, but in the case of arrays it could be a
 * tracking key allocated for the object.
 */
type TrackingKey = PropertyKey & {
    __brand: 'FieldIdentity';
};
type ChildNodeCtor = (key: string, trackingKey: TrackingKey | undefined, isArray: boolean) => FieldNode;
/** Structural component of a `FieldNode` which tracks its path, parent, and children. */
declare abstract class FieldNodeStructure {
    /**
     * Computed map of child fields, based on the current value of this field.
     *
     * This structure reacts to `this.value` and produces a new `ChildrenData` when the
     * value changes structurally (fields added/removed/moved).
     */
    protected abstract readonly childrenMap: Signal<ChildrenData | undefined>;
    /** The field's value. */
    abstract readonly value: WritableSignal<unknown>;
    /**
     * The key of this field in its parent field.
     * Attempting to read this for the root field will result in an error being thrown.
     */
    abstract readonly keyInParent: Signal<string>;
    /** The field manager responsible for managing this field. */
    abstract readonly fieldManager: FormFieldManager;
    /** The root field that this field descends from. */
    abstract readonly root: FieldNode;
    /** The list of property keys to follow to get from the `root` to this field. */
    abstract readonly pathKeys: Signal<readonly string[]>;
    /** The parent field of this field. */
    abstract readonly parent: FieldNode | undefined;
    readonly logic: LogicNode;
    readonly node: FieldNode;
    readonly createChildNode: ChildNodeCtor;
    /** Added to array elements for tracking purposes. */
    readonly identitySymbol: symbol;
    /** Lazily initialized injector. Do not access directly, access via `injector` getter instead. */
    private _injector;
    /** Lazily initialized injector. */
    get injector(): DestroyableInjector;
    constructor(logic: LogicNode, node: FieldNode, createChildNode: ChildNodeCtor);
    /** Gets the child fields of this field. */
    children(): readonly FieldNode[];
    /** Retrieve a child `FieldNode` of this node by property key. */
    getChild(key: PropertyKey): FieldNode | undefined;
    /**
     * Perform a reduction over a field's children (if any) and return the result.
     *
     * Optionally, the reduction is short circuited based on the provided `shortCircuit` function.
     */
    reduceChildren<T>(initialValue: T, fn: (child: FieldNode, value: T) => T, shortCircuit?: (value: T) => boolean): T;
    /** Destroys the field when it is no longer needed. */
    destroy(): void;
    /**
     * Creates a keyInParent signal for a field node.
     *
     * For root nodes, returns ROOT_KEY_IN_PARENT which throws when accessed.
     * For child nodes, creates a computed that tracks the field's current key in its parent,
     * with special handling for tracked array elements.
     *
     * @param options The field node options
     * @param identityInParent The tracking identity (only for tracked array children)
     * @param initialKeyInParent The initial key in parent (only for child nodes)
     * @returns A signal representing the field's key in its parent
     */
    protected createKeyInParent(options: FieldNodeOptions, identityInParent: TrackingKey | undefined, initialKeyInParent: string | undefined): Signal<string>;
    protected createChildrenMap(): Signal<ChildrenData | undefined>;
    /**
     * Creates a "reader" computed for the given key.
     *
     * A reader is a computed signal that memoizes the access of the `FieldNode` stored at this key
     * (or returns `undefined` if no such field exists). Accessing fields via the reader ensures that
     * reactive consumers aren't notified unless the field at a key actually changes.
     */
    private createReader;
}
/** The structural component of a `FieldNode` that is the root of its field tree. */
declare class RootFieldNodeStructure extends FieldNodeStructure {
    readonly fieldManager: FormFieldManager;
    readonly value: WritableSignal<unknown>;
    get parent(): undefined;
    get root(): FieldNode;
    get pathKeys(): Signal<readonly string[]>;
    get keyInParent(): Signal<string>;
    protected readonly childrenMap: Signal<ChildrenData | undefined>;
    /**
     * Creates the structure for the root node of a field tree.
     *
     * @param node The full field node that this structure belongs to
     * @param pathNode The path corresponding to this node in the schema
     * @param logic The logic to apply to this field
     * @param fieldManager The field manager for this field
     * @param value The value signal for this field
     * @param adapter Adapter that knows how to create new fields and appropriate state.
     * @param createChildNode A factory function to create child nodes for this field.
     */
    constructor(
    /** The full field node that corresponds to this structure. */
    node: FieldNode, logic: LogicNode, fieldManager: FormFieldManager, value: WritableSignal<unknown>, createChildNode: ChildNodeCtor);
}
/** The structural component of a child `FieldNode` within a field tree. */
declare class ChildFieldNodeStructure extends FieldNodeStructure {
    readonly logic: LogicNode;
    readonly parent: ParentFieldNode;
    readonly root: FieldNode;
    readonly pathKeys: Signal<readonly string[]>;
    readonly keyInParent: Signal<string>;
    readonly value: WritableSignal<unknown>;
    readonly childrenMap: Signal<ChildrenData | undefined>;
    get fieldManager(): FormFieldManager;
    /**
     * Creates the structure for a child field node in a field tree.
     *
     * @param node The full field node that this structure belongs to
     * @param pathNode The path corresponding to this node in the schema
     * @param logic The logic to apply to this field
     * @param parent The parent field node for this node
     * @param identityInParent The identity used to track this field in its parent
     * @param initialKeyInParent The key of this field in its parent at the time of creation
     * @param adapter Adapter that knows how to create new fields and appropriate state.
     * @param createChildNode A factory function to create child nodes for this field.
     */
    constructor(node: FieldNode, logic: LogicNode, parent: ParentFieldNode, identityInParent: TrackingKey | undefined, initialKeyInParent: string, createChildNode: ChildNodeCtor);
}
/** Options passed when constructing a root field node. */
interface RootFieldNodeOptions {
    /** Kind of node, used to differentiate root node options from child node options. */
    readonly kind: 'root';
    /** The path node corresponding to this field in the schema. */
    readonly pathNode: FieldPathNode;
    /** The logic to apply to this field. */
    readonly logic: LogicNode;
    /** The value signal for this field. */
    readonly value: WritableSignal<unknown>;
    /** The field manager for this field. */
    readonly fieldManager: FormFieldManager;
    /** This allows for more granular field and state management, and is currently used for compat. */
    readonly fieldAdapter: FieldAdapter;
}
/** Options passed when constructing a child field node. */
interface ChildFieldNodeOptions {
    /** Kind of node, used to differentiate root node options from child node options. */
    readonly kind: 'child';
    /** The parent field node of this field. */
    readonly parent: ParentFieldNode;
    /** The path node corresponding to this field in the schema. */
    readonly pathNode: FieldPathNode;
    /** The logic to apply to this field. */
    readonly logic: LogicNode;
    /** The key of this field in its parent at the time of creation. */
    readonly initialKeyInParent: string;
    /** The identity used to track this field in its parent. */
    readonly identityInParent: TrackingKey | undefined;
    /** This allows for more granular field and state management, and is currently used for compat. */
    readonly fieldAdapter: FieldAdapter;
}
/** Options passed when constructing a field node. */
type FieldNodeOptions = RootFieldNodeOptions | ChildFieldNodeOptions;
/**
 * Derived data regarding child fields for a specific parent field.
 */
interface ChildrenData {
    /**
     * Tracks `ChildData` for each property key within the parent.
     */
    readonly byPropertyKey: ReadonlyMap<string, ChildData>;
    /**
     * Tracks the instance of child `FieldNode`s by their tracking key, which is always 1:1 with the
     * fields, even if they move around in the parent.
     */
    readonly byTrackingKey?: ReadonlyMap<TrackingKey, FieldNode>;
}
/**
 * Data for a specific child within a parent.
 */
interface ChildData {
    /**
     * A computed signal to access the `FieldNode` currently stored at a specific key.
     *
     * Because this is a computed, it only updates whenever the `FieldNode` at that key changes.
     * Because `ChildData` is always associated with a specific key via `ChildrenData.byPropertyKey`,
     * this computed gives a stable way to watch the field stored for a given property and only
     * receives notifications when that field changes.
     */
    readonly reader: Signal<FieldNode | undefined>;
    /**
     * The child `FieldNode` currently stored at this key.
     */
    node: FieldNode;
}

/**
 * Manages the collection of fields associated with a given `form`.
 *
 * Fields are created implicitly, through reactivity, and may create "owned" entities like effects
 * or resources. When a field is no longer connected to the form, these owned entities should be
 * destroyed, which is the job of the `FormFieldManager`.
 */
declare class FormFieldManager {
    readonly injector: Injector;
    readonly rootName: string;
    constructor(injector: Injector, rootName: string | undefined);
    /**
     * Contains all child field structures that have been created as part of the current form.
     * New child structures are automatically added when they are created.
     * Structures are destroyed and removed when they are no longer reachable from the root.
     */
    readonly structures: Set<FieldNodeStructure>;
    /**
     * Creates an effect that runs when the form's structure changes and checks for structures that
     * have become unreachable to clean up.
     *
     * For example, consider a form wrapped around the following model: `signal([0, 1, 2])`.
     * This form would have 4 nodes as part of its structure tree.
     * One structure for the root array, and one structure for each element of the array.
     * Now imagine the data is updated: `model.set([0])`. In this case the structure for the first
     * element can still be reached from the root, but the structures for the second and third
     * elements are now orphaned and not connected to the root. Thus they will be destroyed.
     *
     * @param root The root field structure.
     */
    createFieldManagementEffect(root: FieldNodeStructure): void;
    /**
     * Collects all structures reachable from the given structure into the given set.
     *
     * @param structure The root structure
     * @param liveStructures The set of reachable structures to populate
     */
    private markStructuresLive;
}

/**
 * Adapter allowing customization of the creation logic for a field and its associated
 * structure and state.
 */
interface FieldAdapter {
    /**
     * Creates a node structure.
     * @param node
     * @param options
     */
    createStructure(node: FieldNode, options: FieldNodeOptions): FieldNodeStructure;
    /**
     * Creates node validation state
     * @param param
     * @param options
     */
    createValidationState(param: FieldNode, options: FieldNodeOptions): ValidationState;
    /**
     * Creates node state.
     * @param param
     * @param options
     */
    createNodeState(param: FieldNode, options: FieldNodeOptions): FieldNodeState;
    /**
     * Creates a custom child node.
     * @param options
     */
    newChild(options: ChildFieldNodeOptions): FieldNode;
    /**
     * Creates a custom root node.
     * @param fieldManager
     * @param model
     * @param pathNode
     * @param adapter
     */
    newRoot<TValue>(fieldManager: FormFieldManager, model: WritableSignal<TValue>, pathNode: FieldPathNode, adapter: FieldAdapter): FieldNode;
}

/**
 * Options that may be specified when creating a form.
 *
 * @category structure
 * @experimental 21.0.0
 */
interface FormOptions {
    /**
     * The injector to use for dependency injection. If this is not provided, the injector for the
     * current [injection context](guide/di/dependency-injection-context), will be used.
     */
    injector?: Injector;
    name?: string;
    /**
     * Adapter allows managing fields in a more flexible way.
     * Currently this is used to support interop with reactive forms.
     */
    adapter?: FieldAdapter;
}
/**
 * Creates a form wrapped around the given model data. A form is represented as simply a `FieldTree`
 * of the model data.
 *
 * `form` uses the given model as the source of truth and *does not* maintain its own copy of the
 * data. This means that updating the value on a `FieldState` updates the originally passed in model
 * as well.
 *
 * @example
 * ```ts
 * const nameModel = signal({first: '', last: ''});
 * const nameForm = form(nameModel);
 * nameForm.first().value.set('John');
 * nameForm().value(); // {first: 'John', last: ''}
 * nameModel(); // {first: 'John', last: ''}
 * ```
 *
 * @param model A writable signal that contains the model data for the form. The resulting field
 * structure will match the shape of the model and any changes to the form data will be written to
 * the model.
 * @return A `FieldTree` representing a form around the data model.
 * @template TModel The type of the data model.
 *
 * @category structure
 * @experimental 21.0.0
 */
declare function form<TModel>(model: WritableSignal<TModel>): FieldTree<TModel>;
/**
 * Creates a form wrapped around the given model data. A form is represented as simply a `FieldTree`
 * of the model data.
 *
 * `form` uses the given model as the source of truth and *does not* maintain its own copy of the
 * data. This means that updating the value on a `FieldState` updates the originally passed in model
 * as well.
 *
 * @example
 * ```ts
 * const nameModel = signal({first: '', last: ''});
 * const nameForm = form(nameModel);
 * nameForm.first().value.set('John');
 * nameForm().value(); // {first: 'John', last: ''}
 * nameModel(); // {first: 'John', last: ''}
 * ```
 *
 * The form can also be created with a schema, which is a set of rules that define the logic for the
 * form. The schema can be either a pre-defined schema created with the `schema` function, or a
 * function that builds the schema by binding logic to a parts of the field structure.
 *
 * @example
 * ```ts
 * const nameForm = form(signal({first: '', last: ''}), (name) => {
 *   required(name.first);
 *   pattern(name.last, /^[a-z]+$/i, {message: 'Alphabet characters only'});
 * });
 * nameForm().valid(); // false
 * nameForm().value.set({first: 'John', last: 'Doe'});
 * nameForm().valid(); // true
 * ```
 *
 * @param model A writable signal that contains the model data for the form. The resulting field
 * structure will match the shape of the model and any changes to the form data will be written to
 * the model.
 * @param schemaOrOptions The second argument can be either
 *   1. A schema or a function used to specify logic for the form (e.g. validation, disabled fields, etc.).
 *      When passing a schema, the form options can be passed as a third argument if needed.
 *   2. The form options
 * @return A `FieldTree` representing a form around the data model
 * @template TValue The type of the data model.
 *
 * @category structure
 * @experimental 21.0.0
 */
declare function form<TModel>(model: WritableSignal<TModel>, schemaOrOptions: SchemaOrSchemaFn<TModel> | FormOptions): FieldTree<TModel>;
/**
 * Creates a form wrapped around the given model data. A form is represented as simply a `FieldTree`
 * of the model data.
 *
 * `form` uses the given model as the source of truth and *does not* maintain its own copy of the
 * data. This means that updating the value on a `FieldState` updates the originally passed in model
 * as well.
 *
 * @example
 * ```ts
 * const nameModel = signal({first: '', last: ''});
 * const nameForm = form(nameModel);
 * nameForm.first().value.set('John');
 * nameForm().value(); // {first: 'John', last: ''}
 * nameModel(); // {first: 'John', last: ''}
 * ```
 *
 * The form can also be created with a schema, which is a set of rules that define the logic for the
 * form. The schema can be either a pre-defined schema created with the `schema` function, or a
 * function that builds the schema by binding logic to a parts of the field structure.
 *
 * @example
 * ```ts
 * const nameForm = form(signal({first: '', last: ''}), (name) => {
 *   required(name.first);
 *   validate(name.last, ({value}) => !/^[a-z]+$/i.test(value()) ? {kind: 'alphabet-only'} : undefined);
 * });
 * nameForm().valid(); // false
 * nameForm().value.set({first: 'John', last: 'Doe'});
 * nameForm().valid(); // true
 * ```
 *
 * @param model A writable signal that contains the model data for the form. The resulting field
 * structure will match the shape of the model and any changes to the form data will be written to
 * the model.
 * @param schema A schema or a function used to specify logic for the form (e.g. validation, disabled fields, etc.)
 * @param options The form options
 * @return A `FieldTree` representing a form around the data model.
 * @template TModel The type of the data model.
 *
 * @category structure
 * @experimental 21.0.0
 */
declare function form<TModel>(model: WritableSignal<TModel>, schema: SchemaOrSchemaFn<TModel>, options: FormOptions): FieldTree<TModel>;
/**
 * Applies a schema to each item of an array.
 *
 * @example
 * ```ts
 * const nameSchema = schema<{first: string, last: string}>((name) => {
 *   required(name.first);
 *   required(name.last);
 * });
 * const namesForm = form(signal([{first: '', last: ''}]), (names) => {
 *   applyEach(names, nameSchema);
 * });
 * ```
 *
 * @param path The target path for an array field whose items the schema will be applied to.
 * @param schema A schema for an element of the array, or function that binds logic to an
 * element of the array.
 * @template TValue The data type of the item field to apply the schema to.
 *
 * @category structure
 * @experimental 21.0.0
 */
declare function applyEach<TValue extends ReadonlyArray<any>>(path: SchemaPath<TValue>, schema: NoInfer<SchemaOrSchemaFn<TValue[number], PathKind.Item>>): void;
declare function applyEach<TValue extends Object>(path: SchemaPath<TValue>, schema: NoInfer<SchemaOrSchemaFn<ItemType<TValue>, PathKind.Child>>): void;
/**
 * Applies a predefined schema to a given `FieldPath`.
 *
 * @example
 * ```ts
 * const nameSchema = schema<{first: string, last: string}>((name) => {
 *   required(name.first);
 *   required(name.last);
 * });
 * const profileForm = form(signal({name: {first: '', last: ''}, age: 0}), (profile) => {
 *   apply(profile.name, nameSchema);
 * });
 * ```
 *
 * @param path The target path to apply the schema to.
 * @param schema The schema to apply to the property
 * @template TValue The data type of the field to apply the schema to.
 *
 * @category structure
 * @experimental 21.0.0
 */
declare function apply<TValue>(path: SchemaPath<TValue>, schema: NoInfer<SchemaOrSchemaFn<TValue>>): void;
/**
 * Conditionally applies a predefined schema to a given `FieldPath`.
 *
 * @param path The target path to apply the schema to.
 * @param logic A `LogicFn<T, boolean>` that returns `true` when the schema should be applied.
 * @param schema The schema to apply to the field when the `logic` function returns `true`.
 * @template TValue The data type of the field to apply the schema to.
 *
 * @category structure
 * @experimental 21.0.0
 */
declare function applyWhen<TValue>(path: SchemaPath<TValue>, logic: LogicFn<TValue, boolean>, schema: NoInfer<SchemaOrSchemaFn<TValue>>): void;
/**
 * Conditionally applies a predefined schema to a given `FieldPath`.
 *
 * @param path The target path to apply the schema to.
 * @param predicate A type guard that accepts a value `T` and returns `true` if `T` is of type
 *   `TNarrowed`.
 * @param schema The schema to apply to the field when `predicate` returns `true`.
 * @template TValue The data type of the field to apply the schema to.
 * @template TNarrowed The data type of the schema (a narrowed type of TValue).
 *
 * @category structure
 * @experimental 21.0.0
 */
declare function applyWhenValue<TValue, TNarrowed extends TValue>(path: SchemaPath<TValue>, predicate: (value: TValue) => value is TNarrowed, schema: SchemaOrSchemaFn<TNarrowed>): void;
/**
 * Conditionally applies a predefined schema to a given `FieldPath`.
 *
 * @param path The target path to apply the schema to.
 * @param predicate A function that accepts a value `T` and returns `true` when the schema
 *   should be applied.
 * @param schema The schema to apply to the field when `predicate` returns `true`.
 * @template TValue The data type of the field to apply the schema to.
 *
 * @category structure
 * @experimental 21.0.0
 */
declare function applyWhenValue<TValue>(path: SchemaPath<TValue>, predicate: (value: TValue) => boolean, schema: NoInfer<SchemaOrSchemaFn<TValue>>): void;
/**
 * Submits a given `FieldTree` using the given action function and applies any submission errors
 * resulting from the action to the field. Submission errors returned by the `action` will be integrated
 * into the field as a `ValidationError` on the sub-field indicated by the `fieldTree` property of the
 * submission error.
 *
 * @example
 * ```ts
 * async function registerNewUser(registrationForm: FieldTree<{username: string, password: string}>) {
 *   const result = await myClient.registerNewUser(registrationForm().value());
 *   if (result.errorCode === myClient.ErrorCode.USERNAME_TAKEN) {
 *     return [{
 *       fieldTree: registrationForm.username,
 *       kind: 'server',
 *       message: 'Username already taken'
 *     }];
 *   }
 *   return undefined;
 * }
 *
 * const registrationForm = form(signal({username: 'god', password: ''}));
 * submit(registrationForm, async (f) => {
 *   return registerNewUser(registrationForm);
 * });
 * registrationForm.username().errors(); // [{kind: 'server', message: 'Username already taken'}]
 * ```
 *
 * @param form The field to submit.
 * @param action An asynchronous action used to submit the field. The action may return submission
 * errors.
 * @template TModel The data type of the field being submitted.
 *
 * @category submission
 * @experimental 21.0.0
 */
declare function submit<TModel>(form: FieldTree<TModel>, action: (form: FieldTree<TModel>) => Promise<TreeValidationResult>): Promise<void>;
/**
 * Creates a `Schema` that adds logic rules to a form.
 * @param fn A **non-reactive** function that sets up reactive logic rules for the form.
 * @returns A schema object that implements the given logic.
 * @template TValue The value type of a `FieldTree` that this schema binds to.
 *
 * @category structure
 * @experimental 21.0.0
 */
declare function schema<TValue>(fn: SchemaFn<TValue>): Schema<TValue>;

export { EmailValidationError, FORM_FIELD, FormField, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MetadataKey, MetadataReducer, MinLengthValidationError, MinValidationError, NgValidationError, PATTERN, PathKind, PatternValidationError, REQUIRED, RequiredValidationError, SchemaPathRules, StandardSchemaValidationError, ValidationError, apply, applyEach, applyWhen, applyWhenValue, createManagedMetadataKey, createMetadataKey, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit };
export type { AsyncValidationResult, ChildFieldContext, CompatFieldState, CompatSchemaPath, Debouncer, DisabledReason, FieldContext, FieldState, FieldTree, FieldValidator, FormFieldBindingOptions, FormOptions, ItemFieldContext, ItemType, LogicFn, MaybeFieldTree, MaybeSchemaPathTree, MetadataSetterType, OneOrMany, ReadonlyArrayLike, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPath, SchemaPathTree, SignalFormsConfig, Subfields, TreeValidationResult, TreeValidator, ValidationResult, ValidationSuccess, Validator, WithField, WithOptionalField, WithoutField };
