import { type NonNullMutableRef, type NonNullRef } from "../types.js";
/** @since 6.0.0 */
export interface SimpleHoverModeContext {
    /**
     * @example Main Usage
     * ```ts
     * onMouseEnter(event) {
     *   const hoverTimeout = hoverTimeoutRef.current;
     *   if (typeof hoverTimeout !== "number" || mode === "touch") {
     *     return;
     *   }
     *
     *   const { id } = event.currentTarget;
     *   clearDisableTimer();
     *   window.clearTimeout(visibilityTimeout.current);
     *   visibilityTimeout.current = window.setTimeout(() => {
     *     enableHoverMode(id);
     *     setVisible(true);
     *   }, hoverTimeout);
     * }
     * ```
     */
    hoverTimeoutRef: NonNullRef<number | undefined>;
    /**
     * @example Main Usage
     * ```ts
     * onMouseLeave() {
     *   if (mode === "touch") {
     *     return
     *   }
     *
     *   startDisableTimer();
     *   window.clearTimeout(visibilityTimeout.current);
     *   visibilityTimeout.current = window.setTimeout(() => {
     *     setVisible(false)
     *   }, leaveTimeoutRef.current);
     * }
     * ```
     */
    leaveTimeoutRef: NonNullRef<number>;
    /**
     * When this is called, the {@link hoverTimeoutRef} will be set to `0` and the
     * {@link HoverModeContext.activeId} will be set to this `activeId` value.
     *
     * @see {@link hoverTimeoutRef} for an example.
     */
    enableHoverMode: (activeId: string) => void;
    /**
     * Disables all hover mode behavior by clearing all timeouts and resetting
     * internal state.
     */
    disableHoverMode: () => void;
    /**
     * @see {@link leaveTimeoutRef} for an example.
     */
    startDisableTimer: () => void;
    /**
     * @see {@link hoverTimeoutRef} for an example.
     */
    clearDisableTimer: () => void;
}
/**
 * @since 2.8.0
 * @since 6.0.0 Uses refs to increase performance by preventing unneeded
 * re-renders of the entire hover mode provider's component tree. The API also
 * changed to support custom hover mode providers.
 */
export interface HoverModeContext extends SimpleHoverModeContext {
    /**
     * This will only be updated if {@link HoverModeConfiguration.forceRerender} is `true`
     */
    activeId: string;
    /**
     * This ref contains the current DOM `id` for the element that is being
     * hovered within the `HoverModeProvider`. This will be an empty string
     * when the hover mode is not active.
     */
    activeIdRef: NonNullMutableRef<string>;
    /**
     * This ref can be used to disable transitions for a group of components using
     * the same hover mode provider. The general flow would be:
     *
     * - set `disableTransition: animatedOnceRef.current` on hover mode components
     * - set `animatedOnceRef.current = true` when the `onEntered` transition callback fires
     * - set `animatedOnceRef.current = false` when the hover mode behavior is
     *   disabled. This would normally be after a timeout for the `onExited`
     *   callback
     */
    animatedOnceRef: NonNullMutableRef<boolean>;
}
/**
 * @since 6.0.0
 */
export interface CreateHoverModeContextOptions {
    /**
     * This should only be used if creating nested hover mode behavior where the
     * hover mode should default to being enabled if a parent element is hovered.
     * So set this to an element's `id` if a parent element is being hovered when
     * the component **mounts**.
     *
     * The use case for this is the `MenuBar` component since after clicking a
     * menu button or hovering it long enough to enable the hover mode, all child
     * menus should also be in the hover mode until the top-most element is
     * closed.
     *
     * @defaultValue `""`
     */
    defaultActiveId?: string;
    /**
     * When this is `undefined`, the hover mode behavior will be disabled.
     * Otherwise, this will be the amount of time to wait on a `mouseenter` event
     * before setting the visibility to `true`.
     *
     * @defaultValue `undefined`
     */
    hoverTimeout?: number;
    /**
     * The amount of time to wait after a `mouseleave` event before setting the
     * visibility to `false`.
     *
     * @defaultValue `0`
     * @since 6.0.0 This was renamed from `exitVisibilityDelay` and the
     * default value changed from `300` to `0`.
     */
    leaveTimeout?: number;
}
/**
 * @since 6.0.0
 */
export declare function createHoverModeContext(options?: CreateHoverModeContextOptions): Readonly<HoverModeContext>;
/** @since 6.0.0 */
export interface HoverModeConfiguration extends CreateHoverModeContextOptions {
    /**
     * The amount of time to wait before disabling the hover mode behavior if none
     * of the components are being hovered.
     *
     * If this is `undefined`, {@link HoverModeContext.startDisableTimer} will do
     * nothing. You must manually call {@link HoverModeContext.disableHoverMode}
     * to disable the hover mode instead.
     */
    disableTimeout?: number;
    /**
     * @defaultValue `false`
     */
    forceRerender?: boolean;
}
/**
 * @example Creating a Hover Mode Group
 * ```tsx
 * import {
 *   type HoverModeContext,
 *   createHoverModeContext,
 *   useHoverModeProvider,
 * } from "@react-md/core/hoverMode/useHoverModeProvider";
 * import {
 *   type ReactElement,
 *   type ReactNode,
 *   createContext,
 *   useContext,
 * } from "react";
 *
 * export interface CustomHoverContext extends HoverModeContext {
 *   // any additional fields in the context
 * }
 *
 * const context = createContext<CustomHoverContext>(
 *   createHoverModeContext()
 *   // you can also provide default values if needed when the context provider
 *   // isn't a parent component. the following are the defaults
 *   // createHoverModeContext({
 *   //    hoverTimeout: undefined,
 *   //    leaveTimeout: 0,
 *   //    defaultActiveId: "",
 *   // })
 * );
 * const { Provider } = context;
 *
 * interface Props extends HoverModeConfiguration {
 *   children: ReactNode;
 * }
 *
 * export function CustomHoverModeProvider({
 *   children,
 *   // change to whatever defaults you want
 *   hoverTimeout = 3000,
 *   leaveTimeout = 3000,
 *   defaultActiveId = "",
 *   disableTimeout = 5000,
 * }: Props): ReactElement {
 *   const context = useHoverModeProvider({
 *     hoverTimeout,
 *     leaveTimeout,
 *     defaultActiveId,
 *     disableTimeout,
 *   });
 *
 *   return <Provider value={context}>{children}</Provider>;
 * }
 * ```
 *
 * @see {@link CreateHoverModeContextOptions}
 * @see {@link useHoverMode}
 * @since 6.0.0 The `HoverModeProvider` component was replaced by this
 * hook implementation. After developing the `MenuBar`, I realized the hover
 * mode should normally be grouped by related components or types instead of a
 * top-level catch all.
 */
export declare function useHoverModeProvider(options: HoverModeConfiguration): Readonly<HoverModeContext>;
