/**
 * Configuration for grid focus behavior
 */
export interface UseGridFocusOptions {
    /**
     * Number of columns in the grid.
     * Used for up/down navigation (moves by this many cells).
     */
    columns: number;
    /**
     * Selector for cells within the grid. This should match ALL grid cell
     * positions in DOM order (including disabled/empty ones) so the hook can
     * preserve the true grid geometry when computing rows and columns.
     *
     * Use {@link UseGridFocusOptions.isCellFocusable} to distinguish cells that
     * can receive focus from those that cannot (disabled or empty). Navigation
     * moves to a target row/column and, if that cell is not focusable, continues
     * in the same direction to the next focusable cell — the geometry is never
     * collapsed to only-focusable cells.
     *
     * @default 'button:not([disabled]), [tabindex]:not([tabindex="-1"])'
     */
    cellSelector?: string;
    /**
     * Predicate determining whether a cell matched by {@link cellSelector} can
     * receive focus. When omitted, every matched cell is considered focusable
     * (backwards-compatible behavior).
     *
     * @param cell A cell element matched by `cellSelector`.
     */
    isCellFocusable?: (cell: HTMLElement) => boolean;
    /**
     * Resolves the element to focus for a given cell. Useful when the cell is a
     * wrapper element (e.g. a `role="gridcell"` div) whose focusable content is a
     * descendant (e.g. a `<button>`). When omitted, the cell itself is focused.
     *
     * @param cell A cell element matched by `cellSelector`.
     */
    getFocusTarget?: (cell: HTMLElement) => HTMLElement | null;
    /**
     * Callback when navigation would go before the first cell.
     * Useful for navigating to previous month in calendars.
     * @param column The column index (0-based) that was focused when navigating
     * @param offset Number of cells to move (1 for horizontal, columns for vertical)
     */
    onNavigateBefore?: (column: number, offset: number) => void;
    /**
     * Callback when navigation would go after the last cell.
     * Useful for navigating to next month in calendars.
     * @param column The column index (0-based) that was focused when navigating
     * @param offset Number of cells to move (1 for horizontal, columns for vertical)
     */
    onNavigateAfter?: (column: number, offset: number) => void;
    /**
     * Callback for Page Up key (e.g., previous month).
     */
    onPageUp?: () => void;
    /**
     * Callback for Page Down key (e.g., next month).
     */
    onPageDown?: () => void;
    /**
     * @deprecated Direction is auto-detected from the container's computed
     * `direction` — omit this. The explicit override is redundant (there's no
     * valid reason to force RTL arrows in an LTR context) and will be removed in
     * an upcoming major.
     *
     * When set, forces whether the grid is right-to-left: ArrowLeft/ArrowRight
     * are swapped so horizontal navigation follows visual direction. When
     * omitted (preferred), the direction is auto-detected from the container's
     * computed `direction` (read lazily on keydown, horizontal arrows only).
     * @default undefined (auto-detect from the container)
     */
    isRtl?: boolean;
    /**
     * Roving-tabindex ownership. When true, the hook manages a single tab stop
     * across the grid: exactly one focusable cell carries `tabindex="0"` and the
     * rest `tabindex="-1"`. The tab stop is stamped on mount and repaired
     * whenever cells mount/unmount or toggle focusable, and moves with arrow
     * navigation. Attach the returned {@link UseGridFocusReturn.handleFocus} to
     * the container's `onFocus` to keep the stop in sync after clicks or
     * programmatic focus.
     *
     * The tab stop is stamped on the resolved focus target (see
     * {@link UseGridFocusOptions.getFocusTarget}), not the cell wrapper, so it
     * works when the focusable element is a descendant of the cell. An existing
     * `tabindex="0"` on a focus target is honored, letting the caller seed which
     * cell is initially tabbable.
     *
     * When false (the default), the hook only *moves* focus (`.focus()`) and
     * never touches `tabindex` — the caller owns tab-stop management.
     * @default false
     */
    hasRovingTabIndex?: boolean;
}
/**
 * Return type for useGridFocus hook
 */
export interface UseGridFocusReturn<T extends HTMLElement = HTMLElement> {
    /**
     * Ref to attach to the grid container element.
     */
    gridRef: React.RefObject<T | null>;
    /**
     * Key down handler to attach to the grid container.
     */
    handleKeyDown: (e: React.KeyboardEvent) => void;
    /**
     * Focus handler to attach to the container's `onFocus`. Keeps the roving tab
     * stop in sync when `hasRovingTabIndex` is enabled; a no-op otherwise, so it
     * is always safe to attach.
     */
    handleFocus: (e: React.FocusEvent) => void;
    /**
     * Focus a specific cell by index.
     */
    focusCell: (index: number) => void;
    /**
     * Focus the first focusable cell.
     */
    focusFirst: () => void;
    /**
     * Focus the last focusable cell.
     */
    focusLast: () => void;
}
/**
 * Hook for managing keyboard navigation within a grid.
 *
 * Implements WAI-ARIA grid pattern:
 * - Arrow keys: Navigate between cells
 * - Home: Move to first cell in row
 * - End: Move to last cell in row
 * - Ctrl+Home: Move to first cell in grid
 * - Ctrl+End: Move to last cell in grid
 * - Page Up/Down: Custom callbacks (e.g., month navigation)
 *
 * The hook enumerates ALL cells matched by `cellSelector` in DOM order and
 * computes row/column over that full set, preserving the true grid geometry
 * even when some cells are disabled or empty. When a move lands on a
 * non-focusable cell (per `isCellFocusable`), it continues in the same
 * direction to the next focusable cell.
 *
 * By default the hook only *moves* focus and leaves `tabindex` management to
 * the caller. Opt into {@link UseGridFocusOptions.hasRovingTabIndex} for a hook
 * that owns a single tab stop (roving tabindex) across the grid — stamping and
 * repairing it as cells mount/unmount or toggle focusable, and moving it with
 * arrow navigation.
 *
 * @example
 * ```
 * const {gridRef, handleKeyDown} = useGridFocus({
 *   columns: 7,
 *   onPageUp: () => navigateMonth(-1),
 *   onPageDown: () => navigateMonth(1),
 * });
 *
 * <div ref={gridRef} role="grid" onKeyDown={handleKeyDown}>
 *   {cells.map(cell => <button role="gridcell">{cell}</button>)}
 * </div>
 * ```
 *
 * Roving-tabindex grid (e.g. a date picker where the cell is a wrapper around
 * a focusable button):
 *
 * @example
 * ```
 * const {gridRef, handleKeyDown, handleFocus} = useGridFocus({
 *   columns: 7,
 *   cellSelector: '[role="gridcell"]',
 *   isCellFocusable: cell => cell.querySelector('button:not([disabled])') != null,
 *   getFocusTarget: cell => cell.querySelector('button'),
 *   hasRovingTabIndex: true,
 * });
 *
 * <div ref={gridRef} role="grid" onKeyDown={handleKeyDown} onFocus={handleFocus}>
 *   {cells}
 * </div>
 * ```
 */
export declare function useGridFocus<T extends HTMLElement = HTMLElement>(options: UseGridFocusOptions): UseGridFocusReturn<T>;
//# sourceMappingURL=useGridFocus.d.ts.map