import { type ReactElement, type PropsWithChildren } from "react";
import { type Destructor } from "@synnaxlabs/x";
import { type z } from "zod";
import { Input } from '../input';
import { type status } from '../status/aether';
import { type RenderProp } from '../util/renderProp';
/** Props for the @see useField hook */
export interface UseFieldProps {
    path: string;
    allowNull?: false;
}
export interface UseNullableFieldProps {
    path: string;
    allowNull: true;
}
/** Return type for the @see useField hook */
export interface UseFieldReturn<I extends Input.Value, O extends Input.Value = I> extends FieldState<I> {
    onChange: (value: O) => void;
    status: status.CrudeSpec;
}
interface UseField {
    <I extends Input.Value, O extends Input.Value = I>(props: UseFieldProps): UseFieldReturn<I, O>;
    <I extends Input.Value, O extends Input.Value = I>(props: UseNullableFieldProps): UseFieldReturn<I, O> | null;
}
export declare const useField: UseField;
export declare const useFieldListener: <I extends unknown>(path: string, callback: (state: FieldState<I>, extra: FormContextValue) => void) => void;
export interface UseChildFieldValuesProps {
    path: string;
    allowNull?: false;
}
export interface UseNullableChildFieldValuesProps {
    path: string;
    allowNull: true;
}
export interface UseChildFieldValues {
    <V extends unknown = unknown>(props: UseChildFieldValuesProps): V;
    <V extends unknown = unknown>(props: UseNullableChildFieldValuesProps): V | null;
}
export declare const useChildFieldValues: UseChildFieldValues;
export interface UseFieldArrayProps {
    path: string;
    updateOnChildren?: boolean;
}
export interface UseFieldArrayReturn<V extends unknown> {
    value: V[];
    push: (value: V | V[]) => void;
    remove: (index: number | number[]) => void;
}
export declare const useFieldArray: <V extends unknown = unknown>({ path, updateOnChildren, }: UseFieldArrayProps) => UseFieldArrayReturn<V>;
export interface FieldProps<I extends Input.Value = string | number, O extends Input.Value = I> extends UseFieldProps, Omit<Input.ItemProps, "children"> {
    children?: RenderProp<Input.Control<I, O>>;
    padHelpText?: boolean;
    visible?: boolean | ((state: FieldState<I>) => boolean);
    hideIfNull?: boolean;
}
export type FieldT<I extends Input.Value, O extends Input.Value = I> = (props: FieldProps<I, O>) => ReactElement | null;
export declare const Field: <I extends unknown = string | number, O extends unknown = I>({ path, children, label, padHelpText, visible, hideIfNull, ...props }: FieldProps<I, O>) => ReactElement | null;
type Listener<V = unknown> = (state: FieldState<V>) => void;
interface FieldState<V = unknown> {
    value: V;
    status: status.CrudeSpec;
    touched: boolean;
}
interface Get {
    <V extends Input.Value>(path: string, allowNull: false): FieldState<V>;
    <V extends Input.Value>(path: string, allowNull: true): FieldState<V> | null;
}
export interface FormContextValue<Z extends z.ZodTypeAny = z.ZodTypeAny> {
    bind: <V>(path: string, callback: Listener<V>, listenToChildren: boolean) => Destructor;
    set: (path: string, value: unknown) => void;
    get: Get;
    value: () => z.output<Z>;
    validate: (path?: string) => boolean;
    has: (path: string) => boolean;
}
export declare const Context: import("react").Context<FormContextValue<z.ZodTypeAny>>;
export declare const useContext: () => FormContextValue;
export interface UseProps<Z extends z.ZodTypeAny = z.ZodTypeAny> {
    values: z.output<Z>;
    sync?: boolean;
    onChange?: (values: z.output<Z>) => void;
    schema?: Z;
}
export declare const use: <Z extends z.ZodTypeAny>({ values, sync, schema, onChange, }: UseProps<Z>) => FormContextValue<Z>;
export declare const Form: (props: PropsWithChildren<FormContextValue>) => ReactElement;
export {};
