import { Component } from 'react';
import { ComponentClass } from 'react';
import { ComponentType } from 'react';
import { Context } from 'react';
import { ErrorInfo } from 'react';
import { ForwardRefExoticComponent } from 'react';
import { FunctionComponentElement } from 'react';
import { PropsWithChildren } from 'react';
import { PropsWithoutRef } from 'react';
import { ProviderProps } from 'react';
import { ReactNode } from 'react';
import { RefAttributes } from 'react';

/**
 * A reusable React [error boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) component.
 * Wrap this component around other React components to "catch" errors and render a fallback UI.
 *
 * This package is built on top of React [error boundaries](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary),
 * so it has all of the advantages and constraints of that API.
 * This means that it can't catch errors during:
 * - Server side rendering</li>
 * - Event handlers
 * - Asynchronous code (including effects)
 *
 * ℹ️ The component provides several ways to render a fallback: `fallback`, `fallbackRender`, and `FallbackComponent`.
 * Refer to the documentation to determine which is best for your application.
 *
 * ℹ️ This is a **client component**. You can only pass props to it that are serializeable or use it in files that have a `"use client";` directive.
 */
export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
    constructor(props: ErrorBoundaryProps);
    static getDerivedStateFromError(error: Error): {
        didCatch: boolean;
        error: Error;
    };
    resetErrorBoundary(...args: unknown[]): void;
    componentDidCatch(error: unknown, info: ErrorInfo): void;
    componentDidUpdate(prevProps: ErrorBoundaryProps, prevState: ErrorBoundaryState): void;
    render(): FunctionComponentElement<ProviderProps<ErrorBoundaryContextType | null>>;
}

export declare const ErrorBoundaryContext: Context<ErrorBoundaryContextType | null>;

export declare type ErrorBoundaryContextType = {
    didCatch: boolean;
    error: unknown | null;
    resetErrorBoundary: (...args: unknown[]) => void;
};

export declare type ErrorBoundaryProps = ErrorBoundaryPropsWithFallback | ErrorBoundaryPropsWithComponent | ErrorBoundaryPropsWithRender;

export declare type ErrorBoundaryPropsWithComponent = ErrorBoundarySharedProps & {
    fallback?: never;
    /**
     * React component responsible for returning a fallback UI based on a thrown value.
     *
     * ```tsx
     * <ErrorBoundary FallbackComponent={Fallback} />
     * ```
     */
    FallbackComponent: ComponentType<FallbackProps>;
    fallbackRender?: never;
};

export declare type ErrorBoundaryPropsWithFallback = ErrorBoundarySharedProps & {
    /**
     * Static content to render in place of an error if one is thrown.
     *
     * ```tsx
     * <ErrorBoundary fallback={<div class="text-red">Something went wrong</div>} />
     * ```
     */
    fallback: ReactNode;
    FallbackComponent?: never;
    fallbackRender?: never;
};

export declare type ErrorBoundaryPropsWithRender = ErrorBoundarySharedProps & {
    fallback?: never;
    FallbackComponent?: never;
    /**
     * [Render prop](https://react.dev/reference/react/Children#calling-a-render-prop-to-customize-rendering) function responsible for returning a fallback UI based on a thrown value.
     *
     * ```tsx
     * <ErrorBoundary fallbackRender={({ error, resetErrorBoundary }) => <div>...</div>} />
     * ```
     */
    fallbackRender: (props: FallbackProps) => ReactNode;
};

declare type ErrorBoundarySharedProps = PropsWithChildren<{
    /**
     * Optional callback to enable e.g. logging error information to a server.
     *
     * @param error Value that was thrown; typically an instance of `Error`
     * @param info React "component stack" identifying where the error was thrown
     */
    onError?: (error: unknown, info: ErrorInfo) => void;
    /**
     * Optional callback to to be notified when an error boundary is "reset" so React can retry the failed render.
     */
    onReset?: (details: {
        reason: "imperative-api";
        args: unknown[];
    } | {
        reason: "keys";
        prev: unknown[] | undefined;
        next: unknown[] | undefined;
    }) => void;
    /**
     * When changed, these keys will reset a triggered error boundary.
     * This can be useful when an error condition may be tied to some specific state (that can be uniquely identified by key).
     * See the the documentation for examples of how to use this prop.
     */
    resetKeys?: unknown[];
}>;

declare type ErrorBoundaryState = {
    didCatch: true;
    error: unknown;
} | {
    didCatch: false;
    error: null;
};

export declare type FallbackProps = {
    error: unknown;
    resetErrorBoundary: (...args: unknown[]) => void;
};

export declare function getErrorMessage(thrown: unknown): string | undefined;

export declare type OnErrorCallback = (error: unknown, info: ErrorInfo) => void;

/**
 * Convenience hook for imperatively showing or dismissing error boundaries.
 *
 * ⚠️ This hook must only be used within an `ErrorBoundary` subtree.
 */
export declare function useErrorBoundary(): {
    /**
     * The currently visible `Error` (if one has been thrown).
     */
    error: unknown | null;
    /**
     * Method to reset and retry the nearest active error boundary (if one is active).
     */
    resetBoundary: () => void;
    /**
     * Trigger the nearest error boundary to display the error provided.
     *
     * ℹ️ React only handles errors thrown during render or during component lifecycle methods (e.g. effects and did-mount/did-update).
     * Errors thrown in event handlers, or after async code has run, will not be caught.
     * This method is a way to imperatively trigger an error boundary during these phases.
     */
    showBoundary: (error: unknown) => void;
};

export declare type UseErrorBoundaryApi = {
    error: unknown | null;
    resetBoundary: () => void;
    showBoundary: (error: unknown) => void;
};

export declare function withErrorBoundary<Type extends ComponentClass<unknown>, Props extends object>(Component: ComponentType<Props>, errorBoundaryProps: ErrorBoundaryProps): ForwardRefExoticComponent<PropsWithoutRef<Props> & RefAttributes<InstanceType<Type>>>;

export { }
