/**
 * useRailsForm — a small, Inertia `useForm`-style hook for submitting React
 * forms to plain Rails controller actions.
 *
 * The hook keeps Rails as the mutation layer: it wires up `fetch`, attaches the
 * CSRF token from the standard Rails `<meta name="csrf-token">` tag (via the
 * existing `authenticityToken` utility), sends/receives JSON, and maps the
 * blessed 422 validation-error shape — `{ errors: { field: ["message"] } }` —
 * onto per-field client state. The matching server side is the opt-in
 * `ReactOnRails::Controller::FormResponders#render_model_errors` concern in the
 * react_on_rails gem, but the hook works against any endpoint that returns the
 * documented shape.
 *
 * v1 scope (https://github.com/shakacode/react_on_rails/issues/3872):
 * submit verbs, `data`/`setData`, `errors`, `processing`, CSRF auto-attach, and
 * 422 error mapping. Deferred to a follow-up: `transform`,
 * `recentlySuccessful`, and file-upload `progress` (which requires an
 * XMLHttpRequest or duplex-stream transport; v1 is fetch-only).
 *
 * Success/redirect handling is intentionally minimal and forward-compatible
 * with the client-routing work in issue #3873: the hook never navigates on its
 * own. It surfaces safe JSON `redirect_to` hints through `onSuccess` / the
 * resolved submit result so the app — or a future router integration — decides
 * what to do.
 */
/** Per-field validation errors: `{ field: ["message", ...] }`. */
export type RailsFormErrors = Record<string, string[]>;
export type RailsFormMethod = 'post' | 'put' | 'patch' | 'delete';
export interface RailsFormSuccessResult {
    ok: true;
    /** Parsed JSON response body, or `null` when the body was empty or not JSON. */
    responseData: unknown;
    /**
     * Redirect target when the server replied with a safe JSON
     * `redirect_to`/`redirectTo` hint. Browser redirect following is disabled for
     * CSRF-bearing submissions; a defensively filtered redirected Response URL is
     * still accepted if a custom fetch implementation returns one.
     * Hints are accepted only when they resolve to the current origin over HTTP(S);
     * non-HTTP schemes such as `javascript:` are ignored.
     * The hook never navigates — pass this to your router or `window.location`.
     * Designed to compose with the client-routing integration in issue #3873.
     */
    redirectTo: string | null;
    response: Response;
}
export interface RailsFormValidationErrorResult {
    ok: false;
    /** Per-field errors mapped from the 422 response body. */
    errors: RailsFormErrors;
    response: Response;
}
export interface RailsFormStaleResult {
    ok: false;
    /**
     * True when this submit was superseded by a newer submit before it settled.
     * Stale submissions do not update form state, run submit callbacks, or reject
     * stale caller `.catch()` handlers after the newer submit has won.
     */
    stale: true;
    response?: Response;
    error?: unknown;
}
export type RailsFormSubmitResult = RailsFormSuccessResult | RailsFormValidationErrorResult | RailsFormStaleResult;
/** Thrown (as a promise rejection) for non-2xx responses other than a mappable 422. */
export declare class RailsFormRequestError extends Error {
    /** The response, with its body stream unread — `.json()`/`.text()` work. */
    readonly response: Response;
    /**
     * Parsed JSON body when the hook already read it (a 422 whose body didn't
     * match the documented errors shape); `undefined` otherwise.
     */
    readonly responseBody: unknown;
    constructor(response: Response, responseBody?: unknown);
}
export interface RailsFormSubmitOptions {
    /** Extra request headers. JSON and CSRF headers are always applied on top. */
    headers?: Record<string, string>;
    /**
     * Called after a 2xx response. If this callback throws, the exception
     * propagates as the submit promise rejection after form state has settled.
     */
    onSuccess?: (result: RailsFormSuccessResult) => void;
    /** Called after a 422 response whose body matched the documented errors shape. */
    onError?: (errors: RailsFormErrors) => void;
}
export interface UseRailsForm<TData extends object> {
    /** Current form data. */
    data: TData;
    /** Set a single field, merge a partial object, or apply an updater function. */
    setData: {
        <K extends keyof TData>(key: K, value: TData[K]): void;
        (valuesOrUpdater: Partial<TData> | ((previousData: TData) => TData)): void;
    };
    /** Per-field validation errors from the last 422 response (or `setError`). */
    errors: RailsFormErrors;
    hasErrors: boolean;
    /** True while a submission is in flight. */
    processing: boolean;
    /** True once the most recent submission succeeded. Reset when a new one starts. */
    wasSuccessful: boolean;
    /** Submit with an explicit HTTP method. */
    submit: (method: RailsFormMethod, url: string, options?: RailsFormSubmitOptions) => Promise<RailsFormSubmitResult>;
    post: (url: string, options?: RailsFormSubmitOptions) => Promise<RailsFormSubmitResult>;
    put: (url: string, options?: RailsFormSubmitOptions) => Promise<RailsFormSubmitResult>;
    patch: (url: string, options?: RailsFormSubmitOptions) => Promise<RailsFormSubmitResult>;
    /** Named `delete` on the hook object; `delete` is reserved in some contexts. */
    delete: (url: string, options?: RailsFormSubmitOptions) => Promise<RailsFormSubmitResult>;
    /**
     * Reset all data (no args) or the given fields to their initial values.
     * Clears matching errors and `wasSuccessful`. "Initial values" are the
     * `initialData` captured on first render (Inertia `useForm` semantics) —
     * later prop changes are not tracked; remount the component to re-seed.
     */
    reset: (...fields: Extract<keyof TData, string>[]) => void;
    /** Clear all errors (no args) or the errors for the given fields. */
    clearErrors: (...fields: string[]) => void;
    /** Manually set the errors for one field (e.g. client-side pre-checks). */
    setError: (field: string, messages: string | string[]) => void;
}
/**
 * React hook for submitting form data to a Rails controller action.
 *
 * ```tsx
 * const form = useRailsForm({ name: '', email: '' });
 * // <input value={form.data.name} onChange={(e) => form.setData('name', e.target.value)} />
 * // {form.errors.name?.[0]}
 * // <form onSubmit={(e) => { e.preventDefault(); void form.post('/contacts'); }}>
 * ```
 *
 * Submissions send `Content-Type: application/json` / `Accept: application/json`
 * with the CSRF token from the Rails csrf-token meta tag. A 422 response with a
 * `{ errors: { field: ["message"] } }` body (the shape rendered by the
 * `render_model_errors` controller concern) populates `errors`; other non-2xx
 * responses reject with `RailsFormRequestError`.
 */
export declare function useRailsForm<TData extends object>(initialData: TData): UseRailsForm<TData>;
//# sourceMappingURL=useRailsForm.d.ts.map