/// <reference types="react" />
import React from 'react';

declare type AsyncChildren<T> = ((state: AsyncState<T>) => React.ReactNode) | React.ReactNode;
declare type InitialChildren<T> = ((state: AsyncInitial<T>) => React.ReactNode) | React.ReactNode;
declare type PendingChildren<T> = ((state: AsyncPending<T>) => React.ReactNode) | React.ReactNode;
declare type FulfilledChildren<T> = ((data: T, state: AsyncFulfilled<T>) => React.ReactNode) | React.ReactNode;
declare type RejectedChildren<T> = ((error: Error, state: AsyncRejected<T>) => React.ReactNode) | React.ReactNode;
declare type SettledChildren<T> = ((state: AsyncFulfilled<T> | AsyncRejected<T>) => React.ReactNode) | React.ReactNode;
declare type PromiseFn<T> = (props: AsyncProps<T>, controller: AbortController) => Promise<T>;
declare type DeferFn<T> = (args: any[], props: AsyncProps<T>, controller: AbortController) => Promise<T>;
interface AbstractAction {
    type: string;
    meta: {
        counter: number;
        [meta: string]: any;
    };
}
declare type Meta = AbstractAction["meta"];
declare type Start = AbstractAction & {
    type: "start";
    payload: () => Promise<void>;
};
declare type Cancel = AbstractAction & {
    type: "cancel";
};
declare type Fulfill<T> = AbstractAction & {
    type: "fulfill";
    payload: T;
};
declare type Reject = AbstractAction & {
    type: "reject";
    payload: Error;
    error: true;
};
declare type AsyncAction<T> = Start | Cancel | Fulfill<T> | Reject;
interface AsyncOptions<T> {
    promise?: Promise<T>;
    promiseFn?: PromiseFn<T>;
    deferFn?: DeferFn<T>;
    watch?: any;
    watchFn?: (props: AsyncProps<T>, prevProps: AsyncProps<T>) => any;
    initialValue?: T;
    onResolve?: (data: T) => void;
    onReject?: (error: Error) => void;
    reducer?: (state: ReducerAsyncState<T>, action: AsyncAction<T>, internalReducer: (state: ReducerAsyncState<T>, action: AsyncAction<T>) => ReducerAsyncState<T>) => AsyncState<T>;
    dispatcher?: (action: AsyncAction<T>, internalDispatch: (action: AsyncAction<T>) => void, props: AsyncProps<T>) => void;
    debugLabel?: string;
    [prop: string]: any;
}
interface AsyncProps<T> extends AsyncOptions<T> {
    children?: AsyncChildren<T>;
}
interface AbstractState<T> {
    initialValue?: T | Error;
    counter: number;
    promise: Promise<T>;
    run: (...args: any[]) => void;
    reload: () => void;
    cancel: () => void;
    setData: (data: T, callback?: () => void) => T;
    setError: (error: Error, callback?: () => void) => Error;
}
declare type AsyncInitial<T, S = AbstractState<T>> = S & {
    initialValue?: undefined;
    data: undefined;
    error: undefined;
    value: undefined;
    startedAt: undefined;
    finishedAt: undefined;
    status: "initial";
    isInitial: false;
    isPending: false;
    isLoading: false;
    isFulfilled: false;
    isResolved: false;
    isRejected: false;
    isSettled: false;
};
declare type AsyncPending<T, S = AbstractState<T>> = S & {
    data: T | undefined;
    error: Error | undefined;
    value: T | Error | undefined;
    startedAt: Date;
    finishedAt: undefined;
    status: "pending";
    isInitial: false;
    isPending: true;
    isLoading: true;
    isFulfilled: false;
    isResolved: false;
    isRejected: false;
    isSettled: false;
};
declare type AsyncFulfilled<T, S = AbstractState<T>> = S & {
    data: T;
    error: undefined;
    value: T;
    startedAt: Date;
    finishedAt: Date;
    status: "fulfilled";
    isInitial: false;
    isPending: false;
    isLoading: false;
    isFulfilled: true;
    isResolved: true;
    isRejected: false;
    isSettled: true;
};
declare type AsyncRejected<T, S = AbstractState<T>> = S & {
    data: T | undefined;
    error: Error;
    value: Error;
    startedAt: Date;
    finishedAt: Date;
    status: "rejected";
    isInitial: false;
    isPending: false;
    isLoading: false;
    isFulfilled: false;
    isResolved: false;
    isRejected: true;
    isSettled: true;
};
declare type BaseAsyncState<T, S> = AsyncInitial<T, S> | AsyncPending<T, S> | AsyncFulfilled<T, S> | AsyncRejected<T, S>;
declare type ReducerBaseState<T> = Omit<AbstractState<T>, "run" | "reload" | "cancel" | "setData" | "setError">;
declare type ReducerAsyncState<T> = BaseAsyncState<T, ReducerBaseState<T>>;
declare type AsyncState<T, S extends AbstractState<T> = AbstractState<T>> = BaseAsyncState<T, S>;

interface InitialProps<T> {
    children?: InitialChildren<T>;
    persist?: boolean;
}
interface PendingProps<T> {
    children?: PendingChildren<T>;
    initial?: boolean;
}
interface FulfilledProps<T> {
    children?: FulfilledChildren<T>;
    persist?: boolean;
}
interface RejectedProps<T> {
    children?: RejectedChildren<T>;
    persist?: boolean;
}
interface SettledProps<T> {
    children?: SettledChildren<T>;
    persist?: boolean;
}
declare class Async<T> extends React.Component<AsyncProps<T>, AsyncState<T>> {
}
declare type GenericAsync = typeof Async & {
    Initial<T>(props: InitialProps<T>): JSX.Element;
    Pending<T>(props: PendingProps<T>): JSX.Element;
    Loading<T>(props: PendingProps<T>): JSX.Element;
    Fulfilled<T>(props: FulfilledProps<T>): JSX.Element;
    Resolved<T>(props: FulfilledProps<T>): JSX.Element;
    Rejected<T>(props: RejectedProps<T>): JSX.Element;
    Settled<T>(props: SettledProps<T>): JSX.Element;
};
declare type AsyncConstructor<T> = React.ComponentClass<AsyncProps<T>> & {
    Initial: React.FC<InitialProps<T>>;
    Pending: React.FC<PendingProps<T>>;
    Loading: React.FC<PendingProps<T>>;
    Fulfilled: React.FC<FulfilledProps<T>>;
    Resolved: React.FC<FulfilledProps<T>>;
    Rejected: React.FC<RejectedProps<T>>;
    Settled: React.FC<SettledProps<T>>;
};
/**
 * createInstance allows you to create instances of Async that are bound to a specific promise.
 * A unique instance also uses its own React context for better nesting capability.
 */
declare function createInstance<T>(defaultOptions?: AsyncProps<T>, displayName?: string): AsyncConstructor<T>;
declare const _default: GenericAsync;

interface FetchOptions<T> extends AsyncOptions<T> {
    defer?: boolean;
    json?: boolean;
}
declare function useAsync<T>(options: AsyncOptions<T>): AsyncState<T>;
declare function useAsync<T>(promiseFn: PromiseFn<T>, options?: AsyncOptions<T>): AsyncState<T>;
declare class FetchError extends Error {
    response: Response;
    constructor(response: Response);
}
declare type OverrideParams = {
    resource?: RequestInfo;
} & Partial<RequestInit>;
interface FetchRun<T> extends Omit<AbstractState<T>, "run"> {
    run(overrideParams: (params?: OverrideParams) => OverrideParams): void;
    run(overrideParams: OverrideParams): void;
    run(ignoredEvent: React.SyntheticEvent): void;
    run(ignoredEvent: Event): void;
    run(): void;
}
/**
 *
 * @param {RequestInfo} resource
 * @param {RequestInit} init
 * @param {FetchOptions} options
 * @returns {AsyncState<T, FetchRun<T>>}
 */
declare function useAsyncFetch<T>(resource: RequestInfo, init: RequestInit, { defer, json, ...options }?: FetchOptions<T>): AsyncState<T, FetchRun<T>>;
declare const _default$1: typeof useAsync;
declare const useFetch: typeof useAsyncFetch;

declare enum StatusTypes {
    initial = "initial",
    pending = "pending",
    fulfilled = "fulfilled",
    rejected = "rejected"
}

declare type GlobalScope = {
    __REACT_ASYNC__: any;
    AbortController?: typeof AbortController;
    fetch: typeof fetch;
};
/**
 * Universal global scope object. In the browser this is `self`, in Node.js and React Native it's `global`.
 * This file is excluded from coverage reporting because these globals are environment-specific so we can't test them all.
 */
declare const globalScope: GlobalScope;

/**
 * Renders only when no promise has started or completed yet.
 *
 * @prop {Function|Node} children Function (passing state) or React node
 * @prop {Object} state React Async state object
 * @prop {boolean} persist Show until we have data, even while pending (loading) or when an error occurred
 */
declare const IfInitial: {
    <T extends {}>({ children, persist, state, }: {
        children?: InitialChildren<T>;
        persist?: boolean | undefined;
        state: AsyncInitial<T, AbstractState<T>> | AsyncPending<T, AbstractState<T>> | AsyncFulfilled<T, AbstractState<T>> | AsyncRejected<T, AbstractState<T>>;
    }): JSX.Element;
    propTypes: {
        children: any;
        state: any;
        persist: any;
    };
};
/**
 * Renders only while pending (promise is loading).
 *
 * @prop {Function|Node} children Function (passing state) or React node
 * @prop {Object} state React Async state object
 * @prop {boolean} initial Show only on initial load (data is undefined)
 */
declare const IfPending: {
    <T extends {}>({ children, initial, state, }: {
        children?: PendingChildren<T>;
        initial?: boolean | undefined;
        state: AsyncInitial<T, AbstractState<T>> | AsyncPending<T, AbstractState<T>> | AsyncFulfilled<T, AbstractState<T>> | AsyncRejected<T, AbstractState<T>>;
    }): JSX.Element;
    propTypes: {
        children: any;
        state: any;
        initial: any;
    };
};
/**
 * Renders only when promise is resolved.
 *
 * @prop {Function|Node} children Function (passing data and state) or React node
 * @prop {Object} state React Async state object
 * @prop {boolean} persist Show old data while pending (promise is loading)
 */
declare const IfFulfilled: {
    <T extends {}>({ children, persist, state, }: {
        children?: FulfilledChildren<T>;
        persist?: boolean | undefined;
        state: AsyncInitial<T, AbstractState<T>> | AsyncPending<T, AbstractState<T>> | AsyncFulfilled<T, AbstractState<T>> | AsyncRejected<T, AbstractState<T>>;
    }): JSX.Element;
    propTypes: {
        children: any;
        state: any;
        persist: any;
    };
};
/**
 * Renders only when promise is rejected.
 *
 * @prop {Function|Node} children Function (passing error and state) or React node
 * @prop {Object} state React Async state object
 * @prop {boolean} persist Show old error while pending (promise is loading)
 */
declare const IfRejected: {
    <T extends {}>({ children, persist, state, }: {
        children?: RejectedChildren<T>;
        persist?: boolean | undefined;
        state: AsyncInitial<T, AbstractState<T>> | AsyncPending<T, AbstractState<T>> | AsyncFulfilled<T, AbstractState<T>> | AsyncRejected<T, AbstractState<T>>;
    }): JSX.Element;
    propTypes: {
        children: any;
        state: any;
        persist: any;
    };
};
/**
 * Renders only when promise is fulfilled or rejected.
 *
 * @prop {Function|Node} children Function (passing state) or React node
 * @prop {Object} state React Async state object
 * @prop {boolean} persist Show old data or error while pending (promise is loading)
 */
declare const IfSettled: {
    <T extends {}>({ children, persist, state, }: {
        children?: SettledChildren<T>;
        persist?: boolean | undefined;
        state: AsyncInitial<T, AbstractState<T>> | AsyncPending<T, AbstractState<T>> | AsyncFulfilled<T, AbstractState<T>> | AsyncRejected<T, AbstractState<T>>;
    }): JSX.Element;
    propTypes: {
        children: any;
        state: any;
        persist: any;
    };
};

declare const neverSettle: Promise<never>;
declare enum ActionTypes {
    start = "start",
    cancel = "cancel",
    fulfill = "fulfill",
    reject = "reject"
}
declare const init: <T>({ initialValue, promise, promiseFn, }: {
    initialValue?: Error | T | undefined;
    promise?: Promise<T> | undefined;
    promiseFn?: PromiseFn<T> | undefined;
}) => AsyncInitial<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">> | AsyncPending<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">> | AsyncFulfilled<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">> | AsyncRejected<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">>;
declare const reducer: <T>(state: AsyncInitial<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">> | AsyncPending<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">> | AsyncFulfilled<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">> | AsyncRejected<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">>, action: AsyncAction<T>) => AsyncInitial<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">> | AsyncPending<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">> | AsyncFulfilled<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">> | AsyncRejected<T, Pick<AbstractState<T>, "initialValue" | "counter" | "promise">>;
declare const dispatchMiddleware: <T>(dispatch: (action: AsyncAction<T>, ...args: any[]) => void) => (action: AsyncAction<T>, ...args: unknown[]) => void;

export default _default;
export { AbstractAction, AbstractState, ActionTypes, _default as Async, AsyncAction, AsyncChildren, AsyncConstructor, AsyncFulfilled, AsyncInitial, AsyncOptions, AsyncPending, AsyncProps, AsyncRejected, AsyncState, Cancel, DeferFn, FetchError, FetchOptions, Fulfill, FulfilledChildren, FulfilledProps, IfFulfilled, IfInitial, IfPending, IfRejected, IfSettled, InitialChildren, InitialProps, Meta, PendingChildren, PendingProps, PromiseFn, ReducerAsyncState, ReducerBaseState, Reject, RejectedChildren, RejectedProps, SettledChildren, SettledProps, Start, StatusTypes, createInstance, dispatchMiddleware, globalScope, init, neverSettle, reducer, _default$1 as useAsync, useFetch };
