/**
* Shared types for Ariakit React components.
* @module Type utilities
*/
import type { AnyObject, EmptyObject } from "@ariakit/utils";
import type * as React from "react";
/**
* Render prop type.
* @template P Props
* @example
* const children: RenderProp = (props) =>
;
*/
export type RenderProp<
P = React.HTMLAttributes & { ref?: React.Ref },
> = (props: P) => React.ReactNode;
/**
* The `wrapElement` prop.
*/
export type WrapElement = (element: React.ReactElement) => React.ReactElement;
/**
* Custom props including the `render` prop.
*/
export interface Options {
wrapElement?: WrapElement;
/**
* Allows the component to be rendered as a different HTML element or React
* component. The value can be a React element or a function that takes in the
* original component props and gives back a React element with the props
* merged.
*
* Some Ariakit components detect the type of the underlying element when
* they mount. If the render element's type may change while the component
* is mounted, pass a
* [`key`](https://react.dev/learn/preserving-and-resetting-state) prop that
* changes with the element type so React remounts the component with the
* new element. Remounting resets uncontrolled state, so keep the relevant
* state controlled:
* ```jsx
* setChecked(!checked)}
* render={custom ? : }
* />
* ```
*
* Check out the [Composition](https://ariakit.com/guide/composition) guide
* for more details.
*/
render?: RenderProp | React.ReactElement;
}
/**
* HTML props based on the element type, excluding custom props.
* @template T The element type.
* @template P Custom props.
* @example
* type ButtonHTMLProps = HTMLProps<"button", { custom?: boolean }>;
*/
export type HTMLProps<
T extends React.ElementType,
P extends AnyObject = EmptyObject,
> = Omit, keyof P> & {
[index: `data-${string}`]: unknown;
};
/**
* Props based on the element type, including custom props.
* @template T The element type.
* @template P Custom props.
*/
export type Props<
T extends React.ElementType,
P extends AnyObject = EmptyObject,
> = P & HTMLProps;
/**
* A component hook that supports the `render` prop and returns HTML props based
* on the element type.
* @template T The element type.
* @template P Custom props.
* @example
* type UseButton = Hook<"button", { custom?: boolean }>;
*/
export type Hook<
T extends React.ElementType,
P extends AnyObject = EmptyObject,
> = (
props?: Props,
) => HTMLProps;