import { DependencyList, EffectCallback, MutableRefObject, Dispatch, SetStateAction } from 'react';

declare function useBeforeUnloadEffect(fn: (event: BeforeUnloadEvent) => void, deps: DependencyList): void;
declare function useBeforeUnloadAsyncEffect(fn: (event: BeforeUnloadEvent) => Promise<void>, preventDefault?: boolean): void;

/**
 * Deep compare version of React.useCallback
 * @param fn
 * @param deps
 */
declare function useDeepCompareCallback<T extends (...args: any[]) => any>(fn: T, deps: DependencyList): T;

/**
 * Deep compare version of React.useEffect
 * @param fn
 * @param deps
 */
declare function useDeepCompareEffect(fn: EffectCallback, deps: DependencyList): void;

/**
 * Deep compare version of React.useMemo
 * @param fn
 * @param deps
 */
declare function useDeepCompareMemo<T>(fn: () => T, deps: DependencyList): T;

/**
 * A Hook to define an event handler with an always-stable function identity.
 * @param handler
 * @returns
 * @see https://github.com/facebook/react/issues/14099#issuecomment-440013892
 * @see https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md#internal-implementation
 */
declare function useEventCallback<T extends (...args: any[]) => any>(handler: T): T;

type ICallback = () => void;
/**
 * Execute callback interval in react function components.
 * @param callback
 * @param duration
 */
declare function useInterval(callback: ICallback, duration: number): void;

/**
 * Use previous state.
 * @param value
 * @returns
 */
declare function usePreviousState<T = unknown>(value: T): T;

/**
 * Create a ref which always holds the latest value.
 * @param value
 * @returns
 */
declare function useRefreshRef<T>(value: T): MutableRefObject<T>;

/**
 * Reinitialize the state if the related props changed..
 * @param initialState
 * @returns
 */
declare function useSyncState<S>(initialState: S): [S, Dispatch<SetStateAction<S>>];

export { useBeforeUnloadAsyncEffect, useBeforeUnloadEffect, useDeepCompareCallback, useDeepCompareEffect, useDeepCompareMemo, useEventCallback, useInterval, usePreviousState, useRefreshRef, useSyncState };
