import { Select } from '../select';
import { RenderProp } from '../util/renderProp';
import { status } from '../status/aether';
import { Input } from '../input';
import { z } from 'zod';
import { Destructor, Key, Keyed } from '@synnaxlabs/x';
import { ReactElement, PropsWithChildren, FC } from 'react';

/** Props for the @see useField hook */
export interface UseFieldProps<I, O = I> {
    path: string;
    optional?: false;
    onChange?: (value: O, extra: ContextValue & {
        path: string;
    }) => void;
    defaultValue?: O;
}
export interface UseNullableFieldProps<I, O = I> extends Omit<UseFieldProps<I, O>, "optional"> {
    optional: 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<I, O>): UseFieldReturn<I, O>;
    <I extends Input.Value, O extends Input.Value = I>(props: UseNullableFieldProps<I, O>): UseFieldReturn<I, O> | null;
}
/**
 * Hook for managing a particular field in a form.
 *
 * @param props - The props for the hook
 * @param props.path - The path to the field in the form.
 */
export declare const useField: UseField;
export type UseFieldValue = (<I extends Input.Value, O extends Input.Value = I>(path: string, optional?: false, ctx?: ContextValue) => O) & (<I extends Input.Value, O extends Input.Value = I>(path: string, optional: true, ctx?: ContextValue) => O | null);
export type UseFieldState = (<I extends Input.Value, O extends Input.Value = I>(path: string, optional?: false, ctx?: ContextValue) => FieldState<O>) & (<I extends Input.Value, O extends Input.Value = I>(path: string, optional: true, ctx?: ContextValue) => FieldState<O> | null);
export declare const useFieldState: <I extends unknown, O extends unknown = I>(path: string, optional?: boolean, ctx?: ContextValue) => FieldState<O> | null;
export declare const useFieldValue: UseFieldValue;
export declare const useFieldValid: (path: string) => boolean;
export interface UseFieldListenerProps<I extends Input.Value, Z extends z.ZodTypeAny = z.ZodTypeAny> {
    ctx?: ContextValue<Z>;
    path: string;
    onChange: (state: FieldState<I>, extra: ContextValue) => void;
}
export declare const useFieldListener: <I extends unknown, Z extends z.ZodTypeAny = z.ZodTypeAny>({ path, ctx: override, onChange, }: UseFieldListenerProps<I, Z>) => void;
export interface UseChildFieldValuesProps {
    path: string;
    optional?: false;
}
export interface UseNullableChildFieldValuesProps {
    path: string;
    optional: 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;
    keepOnly: (indices: 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<I, O>, Omit<Input.ItemProps, "children" | "onChange" | "defaultValue"> {
    children?: RenderProp<Input.Control<I, O>>;
    padHelpText?: boolean;
    visible?: boolean | ((state: FieldState<I>, ctx: ContextValue) => 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, optional, defaultValue, onChange, className, ...props }: FieldProps<I, O>) => ReactElement | null;
export interface FieldBuilderProps<I extends Input.Value, O extends Input.Value, P extends {}> {
    fieldKey?: string;
    fieldProps?: Partial<FieldProps<I, O>>;
    inputProps?: Partial<P>;
}
export interface BuiltFieldProps<I extends Input.Value, O extends Input.Value, P extends {}> extends FieldProps<I, O> {
    inputProps?: Partial<P>;
    fieldKey?: string;
}
export declare const fieldBuilder: <I extends unknown, O extends unknown, P extends {}>(Component: FC<P & Input.Control<I, O>>) => ({ fieldKey: baseFieldKey, fieldProps, inputProps: baseInputProps, }: FieldBuilderProps<I, O, P>) => FC<BuiltFieldProps<I, O, P>>;
export declare const buildNumericField: ({ fieldKey: baseFieldKey, fieldProps, inputProps: baseInputProps, }: FieldBuilderProps<number, number, Input.NumericProps & import('react').RefAttributes<HTMLInputElement>>) => FC<BuiltFieldProps<number, number, Input.NumericProps & import('react').RefAttributes<HTMLInputElement>>>;
export declare const NumericField: FC<BuiltFieldProps<number, number, Input.NumericProps & import('react').RefAttributes<HTMLInputElement>>>;
export declare const buildTextField: ({ fieldKey: baseFieldKey, fieldProps, inputProps: baseInputProps, }: FieldBuilderProps<string, string, Input.TextProps & import('react').RefAttributes<HTMLInputElement>>) => FC<BuiltFieldProps<string, string, Input.TextProps & import('react').RefAttributes<HTMLInputElement>>>;
export declare const TextField: FC<BuiltFieldProps<string, string, Input.TextProps & import('react').RefAttributes<HTMLInputElement>>>;
export declare const buildSwitchField: ({ fieldKey: baseFieldKey, fieldProps, inputProps: baseInputProps, }: FieldBuilderProps<boolean, boolean, Input.SwitchProps & import('react').RefAttributes<HTMLInputElement>>) => FC<BuiltFieldProps<boolean, boolean, Input.SwitchProps & import('react').RefAttributes<HTMLInputElement>>>;
export declare const SwitchField: FC<BuiltFieldProps<boolean, boolean, Input.SwitchProps & import('react').RefAttributes<HTMLInputElement>>>;
export declare const buildSelectSingleField: <K extends Key, E extends Keyed<K>>({ fieldProps, inputProps, }: FieldBuilderProps<K, K, Select.SingleProps<K, E>>) => FC<BuiltFieldProps<K, K, Select.SingleProps<K, E>>>;
export declare const buildSelectMultiField: <K extends Key, E extends Keyed<K>>({ fieldProps, inputProps, }: FieldBuilderProps<K, K, Select.MultipleProps<K, E>>) => FC<BuiltFieldProps<K, K, Select.MultipleProps<K, E>>>;
export declare const buildButtonSelectField: <K extends Key, E extends Keyed<K>>({ fieldProps, inputProps, }: FieldBuilderProps<K, K, Select.DropdownButtonProps<K, E>>) => FC<BuiltFieldProps<K, K, Select.DropdownButtonProps<K, E>>>;
export type Listener<V = unknown> = (state: FieldState<V>) => void;
export interface FieldState<V = unknown> {
    value: V;
    status: status.CrudeSpec;
    touched: boolean;
    required: boolean;
}
interface RequiredGetProps {
    path: string;
    optional?: boolean;
}
interface OptionalGetProps {
    path: string;
    optional: true;
}
interface GetFunc {
    <V extends Input.Value>(props: RequiredGetProps): FieldState<V>;
    <V extends Input.Value>(props: OptionalGetProps): FieldState<V> | null;
}
interface SetProps {
    path: string;
    value: unknown;
}
type SetFunc = (props: SetProps) => void;
interface BindProps<V = unknown> {
    path: string;
    onChange: Listener<V>;
    listenToChildren?: boolean;
}
type BindFunc = <V = unknown>(props: BindProps<V>) => Destructor;
export interface ContextValue<Z extends z.ZodTypeAny = z.ZodTypeAny> {
    bind: BindFunc;
    set: SetFunc;
    get: GetFunc;
    value: () => z.output<Z>;
    validate: (path?: string) => boolean;
    validateAsync: (path?: string) => Promise<boolean>;
    has: (path: string) => boolean;
}
export declare const Context: import('react').Context<ContextValue<z.ZodTypeAny>>;
export declare const useContext: <Z extends z.ZodTypeAny = z.ZodTypeAny>(override?: ContextValue<Z>) => ContextValue<Z>;
export interface UseProps<Z extends z.ZodTypeAny> {
    values: z.output<Z>;
    sync?: boolean;
    onChange?: (values: z.output<Z>) => void;
    schema?: Z;
}
export type UseReturn<Z extends z.ZodTypeAny> = ContextValue<Z>;
export declare const use: <Z extends z.ZodTypeAny>({ values, sync, schema, onChange, }: UseProps<Z>) => UseReturn<Z>;
export declare const Form: (props: PropsWithChildren<ContextValue>) => ReactElement;
export {};
//# sourceMappingURL=Form.d.ts.map