/**
  * @reach/utils v0.18.0
  *
  * Copyright (c) 2018-2022, React Training LLC
  *
  * This source code is licensed under the MIT license found in the
  * LICENSE.md file in the root directory of this source tree.
  *
  * @license MIT
  */

import * as React$1 from 'react';
import { useEffect } from 'react';

declare function canUseDOM(): boolean;

/**
 * Type-safe clone element
 *
 * @param element
 * @param props
 * @param children
 */
declare function cloneValidElement<Props>(element: React$1.ReactElement<Props> | React$1.ReactNode, props?: Partial<Props> & React$1.Attributes, ...children: React$1.ReactNode[]): React$1.ReactElement<Props> | React$1.ReactNode;

/**
 * Wraps a lib-defined event handler and a user-defined event handler, returning
 * a single handler that allows a user to prevent lib-defined handlers from
 * firing.
 *
 * @param theirHandler User-supplied event handler
 * @param ourHandler Library-supplied event handler
 */
declare function composeEventHandlers<EventType extends React.SyntheticEvent | Event>(theirHandler: ((event: EventType) => any) | undefined, ourHandler: (event: EventType) => any): (event: EventType) => any;

/**
 * React.Ref uses the readonly type `React.RefObject` instead of
 * `React.MutableRefObject`, We pretty much always assume ref objects are
 * mutable (at least when we create them), so this type is a workaround so some
 * of the weird mechanics of using refs with TS.
 */
declare type AssignableRef<ValueType> = {
    bivarianceHack(instance: ValueType | null): void;
}["bivarianceHack"] | React$1.MutableRefObject<ValueType | null>;
/**
 * Type can be either a single `ValueType` or an array of `ValueType`
 */
declare type SingleOrArray<ValueType> = ValueType[] | ValueType;
/**
 * The built-in utility type `Omit` does not distribute over unions. So if you
 * have:
 *
 *    type A = { a: 'whatever' }
 *
 * and you want to do a union with:
 *
 *    type B = A & { b: number } | { b: string; c: number }
 *
 * you might expect `Omit<B, 'a'>` to give you:
 *
 *    type B =
 *      | Omit<{ a: "whatever"; b: number }, "a">
        | Omit<{ a: "whatever"; b: string; c: number }, "a">;
 *
 * This is not the case, unfortunately, so we need to create our own version of
 * `Omit` that distributes over unions with a distributive conditional type. If
 * you have a generic type parameter `T`, then the construct
 * `T extends any ? F<T> : never` will end up distributing the `F<>` operation
 * over `T` when `T` is a union type.
 *
 * @link https://stackoverflow.com/a/59796484/1792019
 * @link http://www.typescriptlang.org/docs/handbook/advanced-types.html#distributive-conditional-types
 */
declare type DistributiveOmit<BaseType, Key extends PropertyKey> = BaseType extends any ? Omit<BaseType, Key> : never;
declare type ElementTagNameMap = HTMLElementTagNameMap & Pick<SVGElementTagNameMap, Exclude<keyof SVGElementTagNameMap, keyof HTMLElementTagNameMap>>;

/**
 * Passes or assigns an arbitrary value to a ref function or object.
 *
 * @param ref
 * @param value
 */
declare function assignRef<RefValueType = any>(ref: AssignableRef<RefValueType> | null | undefined, value: any): void;
/**
 * Passes or assigns a value to multiple refs (typically a DOM node). Useful for
 * dealing with components that need an explicit ref for DOM calculations but
 * also forwards refs assigned by an app.
 *
 * @param refs Refs to fork
 */
declare function useComposedRefs<RefValueType = any>(...refs: (AssignableRef<RefValueType> | null | undefined)[]): (node: any) => void;

/**
 * Get computed style properties of a DOM element.
 *
 * @param element
 */
declare function getComputedStyles(element: Element): CSSStyleDeclaration | null;
/**
 * Get a computed style value by property.
 *
 * @param element
 * @param styleProp
 */
declare function getComputedStyle(element: Element, styleProp: string): string | null;

/** @deprecated */
declare function createNamedContext<ContextValueType>(name: string, defaultValue: ContextValueType): React$1.Context<ContextValueType>;
declare type ContextProvider<T> = React$1.FC<React$1.PropsWithChildren<T>>;
declare function createContext<ContextValueType extends object | null>(rootComponentName: string, defaultContext?: ContextValueType): [
    ContextProvider<ContextValueType>,
    (callerComponentName: string) => ContextValueType
];

/**
 * Logs a warning in dev mode when a component switches from controlled to
 * uncontrolled, or vice versa
 *
 * A single prop should typically be used to determine whether or not a
 * component is controlled or not.
 *
 * @param controlledValue
 * @param controlledPropName
 * @param componentName
 */
declare function useControlledSwitchWarning(controlledValue: any, controlledPropName: string, componentName: string): void;

/**
 * Get the size of the working document minus the scrollbar offset.
 *
 * @param element
 */
declare function getDocumentDimensions(element?: HTMLElement | null | undefined): {
    width: number;
    height: number;
};

/**
 * Get the scoll position of the global window object relative to a given node.
 *
 * @param element
 */
declare function getScrollPosition(element?: HTMLElement | null | undefined): {
    scrollX: number;
    scrollY: number;
};

/**
 * Get the scrollbar offset distance.
 *
 * TODO: Remove in 1.0 (we used this in public examples)
 */
declare function getScrollbarOffset(): number;

/**
 * Detects right clicks
 *
 * @param nativeEvent
 */
declare function isRightClick(nativeEvent: MouseEvent | PointerEvent | TouchEvent): boolean;

/**
 * Joins strings to format IDs for compound components.
 *
 * @param args
 */
declare function makeId(...args: (string | number | null | undefined)[]): string;

declare function noop(): void;

/**
 * Get an element's owner document. Useful when components are used in iframes
 * or other environments like dev tools.
 *
 * @param element
 */
declare function getOwnerDocument<T extends Element>(element: T | null | undefined): Document | null;
/**
 * TODO: Remove in 1.0
 */
declare function getOwnerWindow<T extends Element>(element: T | null | undefined): (Window & typeof globalThis) | null;

/**
 * Checks whether or not a value is a boolean.
 *
 * @param value
 */
declare function isBoolean(value: any): value is boolean;
/**
 * Checks whether or not a value is a function.
 *
 * @param value
 */
declare function isFunction(value: any): value is Function;
/**
 * Checks whether or not a value is a number.
 *
 * @param value
 */
declare function isNumber(value: any): value is number;
/**
 * Checks whether or not a value is a string.
 *
 * @param value
 */
declare function isString(value: any): value is string;

/**
 * React hook for creating a value exactly once.
 * @see https://github.com/Andarist/use-constant
 */
declare function useConstant<ValueType>(fn: () => ValueType): ValueType;

/**
 * Check if a component is controlled or uncontrolled and return the correct
 * state value and setter accordingly. If the component state is controlled by
 * the app, the setter is a noop.
 *
 * @param controlledValue
 * @param defaultValue
 */
declare function useControlledState<T = any>({ controlledValue, defaultValue, calledFrom, }: {
    controlledValue: T | undefined;
    defaultValue: T | (() => T);
    calledFrom?: string;
}): [T, React$1.Dispatch<React$1.SetStateAction<T>>];

/**
 * Adds a DOM event listener
 *
 * @param eventName
 * @param listener
 * @param element
 */
declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, listener: (event: WindowEventMap[K]) => any, element?: HTMLElement | Document | Window | EventTarget): void;

/**
 * Detect when focus changes in our document.
 *
 * @param handleChange
 * @param when
 * @param ownerDocument
 */
declare function useFocusChange(handleChange?: (activeElement: Element | null, previousActiveElement: Element | null, event?: FocusEvent) => void, when?: "focus" | "blur", ownerDocument?: Document): void;

/**
 * Forces a re-render, similar to `forceUpdate` in class components.
 */
declare function useForceUpdate(): () => void;

/**
 * React currently throws a warning when using useLayoutEffect on the server. To
 * get around it, we can conditionally useEffect on the server (no-op) and
 * useLayoutEffect in the browser. We occasionally need useLayoutEffect to
 * ensure we don't get a render flash for certain operations, but we may also
 * need affected components to render on the server. One example is when setting
 * a component's descendants to retrieve their index values.
 *
 * Important to note that using this hook as an escape hatch will break the
 * eslint dependency warnings unless you rename the import to `useLayoutEffect`.
 * Use sparingly only when the effect won't effect the rendered HTML to avoid
 * any server/client mismatch.
 *
 * If a useLayoutEffect is needed and the result would create a mismatch, it's
 * likely that the component in question shouldn't be rendered on the server at
 * all, so a better approach would be to lazily render those in a parent
 * component after client-side hydration.
 *
 * https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85
 * https://github.com/reduxjs/react-redux/blob/master/src/utils/useIsomorphicLayoutEffect.js
 *
 * @param effect
 * @param deps
 */
declare const useIsomorphicLayoutEffect: typeof useEffect;

declare function useLazyRef<F extends (...args: any[]) => any>(fn: F): React$1.MutableRefObject<ReturnType<F>>;

/**
 * Returns the previous value of a reference after a component update.
 *
 * @param value
 */
declare function usePrevious<ValueType = any>(value: ValueType): ValueType | null;

/**
 * Converts a callback to a ref to avoid triggering re-renders when passed as a
 * prop and exposed as a stable function to avoid executing effects when passed
 * as a dependency.
 */
declare function useStableCallback<T extends (...args: any[]) => any>(callback: T | null | undefined): T;
/**
 * Converts a callback to a ref to avoid triggering re-renders when passed as a
 * prop and exposed as a stable function to avoid executing effects when passed
 * as a dependency.
 *
 * Use this over `useStableCallback` when you want the callback to be cached in
 * `useLayoutEffect` instead of `useEffect` to deal with timing issues only when
 * needed.
 */
declare function useStableLayoutCallback<T extends (...args: any[]) => any>(callback: T | null | undefined): T;

declare function useStatefulRefValue<V>(ref: React.RefObject<V>, initialState: V): [V, (refValue: Exclude<V, null>) => void];

/**
 * Call an effect after a component update, skipping the initial mount.
 *
 * @param effect Effect to call
 * @param deps Effect dependency list
 */
declare function useUpdateEffect(effect: React$1.EffectCallback, deps?: React$1.DependencyList): void;

export { AssignableRef, DistributiveOmit, ElementTagNameMap, SingleOrArray, assignRef, canUseDOM, cloneValidElement, composeEventHandlers, createContext, createNamedContext, getComputedStyle, getComputedStyles, getDocumentDimensions, getOwnerDocument, getOwnerWindow, getScrollPosition, getScrollbarOffset, isBoolean, isFunction, isNumber, isRightClick, isString, makeId, noop, useComposedRefs, useConstant, useControlledState, useControlledSwitchWarning, useEventListener, useFocusChange, useForceUpdate, useIsomorphicLayoutEffect, useLazyRef, usePrevious, useStableCallback, useStableLayoutCallback, useStatefulRefValue, useUpdateEffect };
