import { RefObject } from 'react';

interface AsyncState<T> {
    isLoading: boolean;
    error: Error | null;
    value: T | null;
}
/**
 * Hook that handles async operations with loading and error states
 * @param asyncFunction - Async function to execute
 * @returns Object containing execute function, loading state, error, and value
 */
declare function useAsync<T>(asyncFunction: (...args: any[]) => Promise<T>): {
    execute: (...args: any[]) => Promise<void>;
    status: AsyncState<T>;
};

type Handler = (event: MouseEvent | TouchEvent) => void;
/**
 * Hook that handles click outside of the referenced element
 * @param ref - React ref object for the element to monitor
 * @param handler - Callback function to execute when click outside occurs
 */
declare const useClickOutside: <T extends HTMLElement = HTMLElement>(ref: RefObject<T | null> | null, handler: Handler) => void;

/**
 * Hook that tracks state of a CSS media query
 * @param query - CSS media query string
 * @returns boolean indicating if the media query matches
 */
declare const useMediaQuery: (query: string) => boolean;

/**
 * Hook that detects hover state on an element
 * @param ref - (optional) React ref object for the element to monitor
 * @returns Tuple containing ref to attach to element and boolean indicating hover state
 */
declare const useHover: <T extends HTMLElement>(_ref?: RefObject<T | null> | null) => [RefObject<T>, boolean];

/**
 * Hook that detects when a specific key is pressed
 * @param targetKey - The key to detect (e.g., "Enter", "Escape", "a")
 * @returns boolean indicating if the key is currently pressed
 */
declare function useKeyPress(targetKey: string): boolean;

type KeyCombo = string[];
/**
 * Hook that detects when a specific combination of keys is pressed
 * @param targetCombo - Array of keys that make up the combination (e.g., ["Control", "Shift", "a"])
 * @returns boolean indicating if the combination is currently active
 */
declare function useKeyCombo(targetCombo: KeyCombo): boolean;

/**
 * Configuration options for the useLongPress hook
 */
interface LongPressOptions {
    /** Duration in milliseconds before long press is triggered (default: 400) */
    delay?: number;
    /** Whether to disable context menu on long press (default: true) */
    preventContext?: boolean;
    /** Callback fired when a normal press (shorter than delay) is completed */
    onPress?: () => void;
    /** Callback fired when a long press is successfully triggered */
    onLongPress?: () => void;
    /** Callback fired when a long press is canceled before completion */
    onLongPressCanceled?: () => void;
}
/**
 * A hook that handles both normal press and long press interactions
 *
 * @param options - Configuration options for the long press behavior
 * @param options.delay - Duration in milliseconds before a press is considered a long press (default: 400)
 * @param options.preventContext - When true, prevents the default context menu on long press (default: true)
 * @param options.onPress - Callback fired when a normal press (shorter than delay) is completed.
 *                         Triggers only if the press duration was less than the specified delay
 * @param options.onLongPress - Callback fired when a long press is successfully triggered.
 *                             Triggers exactly once when the press duration exceeds the delay
 * @param options.onLongPressCanceled - Callback fired when a long press is canceled before completion.
 *                                     Triggers if the press is released or canceled before reaching the delay threshold
 * @returns Object containing event handlers and current press state
 *
 * @example
 * ```tsx
 * const MyComponent = () => {
 *   const { handlers, state } = useLongPress({
 *     delay: 1000,
 *     onPress: () => console.log('Normal press'),
 *     onLongPress: () => console.log('Long press completed'),
 *     onLongPressCanceled: () => console.log('Long press canceled'),
 *   });
 *
 *   return (
 *     <button {...handlers}>
 *       {state.isLongPressed
 *         ? 'Long Press!'
 *         : `Hold me (${Math.round(state.progress * 100)}%)`}
 *     </button>
 *   );
 * };
 * ```
 */
declare function useLongPress(options?: LongPressOptions): {
    /** Event handlers to attach to the target element */
    handlers: {
        onMouseDown: (event: React.TouchEvent | React.MouseEvent) => void;
        onMouseUp: (event: React.TouchEvent | React.MouseEvent) => void;
        onMouseLeave: (event: React.TouchEvent | React.MouseEvent) => void;
        onTouchStart: (event: React.TouchEvent | React.MouseEvent) => void;
        onTouchEnd: (event: React.TouchEvent | React.MouseEvent) => void;
        onTouchCancel: (event: React.TouchEvent | React.MouseEvent) => void;
    };
    /** Current state of the press interaction */
    state: {
        isPressed: boolean;
        isLongPressed: boolean;
        progress: number;
    };
};

interface WindowSize {
    width: number;
    height: number;
}
/**
 * Hook that tracks window dimensions
 * @returns Object containing current window width and height
 * @example
 * const { width, height } = useWindowSize();
 * console.log(width, height);
 */
declare function useWindowSize(): WindowSize;

interface ScrollPosition {
    x: number;
    y: number;
}
/**
 * Hook that tracks window scroll position
 * @returns Object containing current scroll x and y coordinates
 */
declare function useScrollPosition(): ScrollPosition;

interface ContainerScroll {
    scrollTop: number;
    scrollLeft: number;
    scrollWidth: number;
    scrollHeight: number;
    clientWidth: number;
    clientHeight: number;
    isScrolling: boolean;
}
/**
 * Hook that tracks scroll position and dimensions of a container element
 * @param containerRef - React ref object pointing to the container element
 * @param delay - Delay in milliseconds before setting isScrolling to false
 * @returns Object containing scroll position and dimension information
 */
declare function useContainerScroll(containerRef: RefObject<HTMLElement | null>, delay?: number): ContainerScroll;

interface ElementSize {
    width: number;
    height: number;
}
/**
 * Hook that tracks an element's dimensions using ResizeObserver
 * @param elementRef - React ref object pointing to the target element
 * @returns Object containing current element width and height
 */
declare function useElementSize(elementRef: RefObject<HTMLElement>): ElementSize;

interface IntersectionOptions extends IntersectionObserverInit {
    freezeOnceVisible?: boolean;
}
/**
 * Hook that tracks element's intersection with viewport using IntersectionObserver
 * @param elementRef - React ref object pointing to the target element
 * @param options - IntersectionObserver options with additional freezeOnceVisible flag
 * @returns IntersectionObserverEntry if available, null otherwise
 */
declare function useIntersectionObserver(elementRef: RefObject<HTMLElement>, { threshold, root, rootMargin, freezeOnceVisible, }?: IntersectionOptions): IntersectionObserverEntry | null;

interface ResizeObserverEntry {
    contentRect: DOMRectReadOnly;
    contentBoxSize: ReadonlyArray<ResizeObserverSize>;
    borderBoxSize: ReadonlyArray<ResizeObserverSize>;
    devicePixelContentBoxSize: ReadonlyArray<ResizeObserverSize>;
    target: Element;
}
/**
 * Hook that tracks element's size changes using ResizeObserver with full entry details
 * @param elementRef - React ref object pointing to the target element
 * @returns Latest ResizeObserverEntry if available, null otherwise
 */
declare function useResizeObserver(elementRef: RefObject<HTMLElement>): ResizeObserverEntry | null;

/**
 * Hook that debounces a value
 * @param value - The value to debounce
 * @param delay - The delay in milliseconds
 * @returns The debounced value
 */
declare function useDebounce<T>(value: T, delay: number): T;

/**
 * Hook that throttles a value
 * @param value - The value to throttle
 * @param interval - The minimum time interval between updates in milliseconds
 * @returns The throttled value
 */
declare function useThrottle<T>(value: T, interval: number): T;

interface TimerControls {
    start: () => void;
    pause: () => void;
    reset: () => void;
    isRunning: boolean;
}
/**
 * Hook that provides a timer with controls
 * @param initialTime - Initial time in seconds
 * @param step - Time step in seconds (default: 1)
 * @param countDown - Whether to count down instead of up (default: false)
 * @returns [currentTime, controls]
 */
declare function useTimer(initialTime: number, step?: number, countDown?: boolean): [number, TimerControls];

/**
 * Hook that sets up an interval that is properly cleaned up when the component unmounts
 * @param callback - Function to call on each interval
 * @param delay - Delay in milliseconds (null to pause)
 */
declare function useInterval(callback: () => void, delay: number | null): void;

type EventMap = WindowEventMap & HTMLElementEventMap & DocumentEventMap;
/**
 * Hook that adds an event listener to a target element or window
 * @param eventName - Name of the event to listen for
 * @param handler - Event handler function
 * @param element - Target element (defaults to window)
 * @param options - AddEventListener options
 */
declare function useEventListener<K extends keyof EventMap>(eventName: K, handler: (event: EventMap[K]) => void, element?: RefObject<HTMLElement> | null, options?: boolean | AddEventListenerOptions): void;

/**
 * Options for configuring cookie behavior
 */
interface CookieOptions {
    /** Number of days until the cookie expires (default: 7) */
    days?: number;
    /** Cookie path (default: "/") */
    path?: string;
    /** Cookie domain */
    domain?: string;
    /** Whether the cookie requires HTTPS (default: false) */
    secure?: boolean;
    /** SameSite cookie attribute (default: "Lax") */
    sameSite?: "Strict" | "Lax" | "None";
}
/**
 * Hook for managing state persisted in a browser cookie
 * @param name - The name of the cookie
 * @param initialValue - The initial value to use if no cookie exists
 * @returns A tuple containing:
 * - The current cookie value (or null if not set)
 * - A function to update the cookie value and its options
 * - A function to delete the cookie
 */
declare function useCookieState(name: string, initialValue: string): [string | null, (newValue: string, options?: CookieOptions) => void, () => void];

/**
 * Hook for managing state persisted in localStorage
 * @param key - The localStorage key
 * @param initialValue - The initial value to use if no value exists in storage
 * @returns A tuple containing the current value and a setter function
 * @example
 * const [value, setValue] = useLocalStorageState('my-key', 'initial value');
 */
declare function useLocalStorageState<T>(key: string, initialValue: T): [T, (value: T | ((val: T) => T)) => void];

/**
 * Hook for managing state persisted in sessionStorage
 * @param key - The sessionStorage key
 * @param initialValue - The initial value to use if no value exists in storage
 * @returns A tuple containing the current value and a setter function
 * @example
 * const [value, setValue] = useSessionStorageState('my-key', 'initial value');
 */
declare function useSessionStorageState<T>(key: string, initialValue: T): [T, (value: T | ((val: T) => T)) => void];

/**
 * Hook for managing state persisted in URL query parameters
 * @param key - The query parameter key
 * @param initialValue - The initial value to use if the parameter doesn't exist
 * @param options - Configuration options
 * @param options.serialize - Function to convert value to string (default: JSON.stringify)
 * @param options.deserialize - Function to parse string back to value (default: JSON.parse)
 * @returns A tuple containing the current value and a setter function
 */
declare function useQueryParamsState<T>(key: string, initialValue: T, options?: {
    serialize?: (value: T) => string;
    deserialize?: (value: string) => T;
}): [T, (value: T | ((val: T) => T)) => void];

export { useAsync, useClickOutside, useContainerScroll, useCookieState, useDebounce, useElementSize, useEventListener, useHover, useIntersectionObserver, useInterval, useKeyCombo, useKeyPress, useLocalStorageState, useLongPress, useMediaQuery, useQueryParamsState, useResizeObserver, useScrollPosition, useSessionStorageState, useThrottle, useTimer, useWindowSize };
