import { type ChangeEvent, type HTMLAttributes, type InputHTMLAttributes, type ReactElement, type ReactNode, type Ref } from "react";
import { type BoxProps } from "../box/Box.js";
import { type MenuProps } from "../menu/Menu.js";
import { type LabelA11y, type PropsWithRef, type RequireAtLeastOne } from "../types.js";
import { type TextFieldContainerProps } from "./TextFieldContainer.js";
import { type UserAgentAutocompleteProps } from "./types.js";
/**
 * This is a convenience type for casting the `event.currentTarget.value` of a
 * `Select`'s change event to be union of available values.
 *
 * Note: The change event does not provide any sort of validation on the value
 * so automation tools like Cypress, Playwright, or Selenium might set an
 * invalid value. This also does not work for numbers, so you will need to
 * implement that yourself.
 *
 * @example Simple Usage
 * ```tsx
 * import type { SelectedChangeEvent } from "@react-md/core";
 * import { Select, Option } from "@react-md/core";
 * import type { ReactElement } from "react";
 *
 * type Value = "" | "a" | "b" | "c" | "d";
 *
 * function Example(): ReactElement {
 *   const [value, setValue] = useState<Value>("");
 *
 *   const handleChange = (event: SelectChangeEvent<Value>): void => {
 *     // No type error!
 *     // `event.currentTarget.value`'s type is `Value` instead of a generic `string`
 *     setValue(event.currentTarget.value);
 *   };
 *
 *   return (
 *     <Select
 *       label="Label"
 *       value={value}
 *       onChange={handleChange}
 *     >
 *       <Option value="a">First</Option>
 *       <Option value="b">Second</Option>
 *       <Option value="c">Third</Option>
 *       <Option value="d">Fourth</Option>
 *     </Select>
 *   );
 * }
 * ```
 * @since 6.0.0
 */
export type SelectChangeEvent<Value extends string> = ChangeEvent<HTMLInputElement> & {
    currentTarget: {
        value: Value;
    };
};
/**
 * @since 6.0.0 Rewritten with a new API.
 */
export interface SelectProps<Value extends string> extends Omit<TextFieldContainerProps, "label">, Pick<InputHTMLAttributes<HTMLInputElement>, "form" | "required">, UserAgentAutocompleteProps {
    /**
     * @defaultValue `"select-" + useId()`
     */
    id?: string;
    /**
     * Optional placeholder text or element to render while no options have been
     * selected.
     */
    placeholder?: ReactNode;
    /**
     * Set this to a custom dropdown icon or `null` to not render a dropdown icon.
     *
     * @defaultValue `getIcon("dropdown")`
     */
    icon?: ReactNode;
    /**
     * Set this value to fully control the value of the select component. The
     * {@link onChange} handler **must** also be provided if this prop exists.
     */
    value?: Value;
    /**
     * An optional default value when the value of the select component is
     * uncontrolled.
     *
     * @defaultValue `""`
     */
    defaultValue?: Value;
    /** @see {@link SelectChangeEvent} */
    onChange?(event: SelectChangeEvent<Value>): void;
    /**
     * An optional floating label to display like other form fields.
     */
    label?: ReactNode;
    /**
     * Optional props to pass to the `<span>` that surrounds the {@link label}
     */
    labelProps?: PropsWithRef<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>;
    /**
     * An optional ref to pass to the hidden `<input type="text" />` element that
     * stores the current value. This is really only useful if you'd like to keep
     * this component uncontrolled and access the value through
     * `inputRef.current.value`.
     */
    inputRef?: Ref<HTMLInputElement>;
    inputProps?: InputHTMLAttributes<HTMLInputElement>;
    /**
     * A ref for the container `<div>` element.
     */
    containerRef?: Ref<HTMLDivElement>;
    /**
     * Any additional props to provide to the `Menu` component that renders all
     * the `Option`s.
     *
     * The menu will always have these default values unless explicity
     * overwritten by this prop:
     *
     * - `aria-labelledby={label ? labelId : id}` -- this will be undefined if
     *   `aria-label` is provided
     * - `anchor={BELOW_CENTER_ANCHOR}`
     * - `width="min"`
     */
    menuProps?: Omit<MenuProps, "visible" | "onRequestClose" | "fixedTo">;
    /**
     * Any additional props to pass to the div that contains the current visible
     * option.
     */
    selectedOptionProps?: BoxProps;
    /**
     * Set this to `true` if all the `Option` components should display the
     * selected icon after the children instead of before.
     *
     * @see {@link disableSelectedIcon} to remove the selected icon instead.
     *
     * @defaultValue `false`
     */
    selectedIconAfter?: boolean;
    /**
     * Set this to `true` to prevent the current option from rendering the
     * `leftAddon` in the `TextFieldContainer`.
     *
     * @defaultValue `false`
     */
    disableOptionAddon?: boolean;
    /**
     * Set this to `true` to update all the `Option` components to no longer
     * render an icon while selected.
     *
     * @defaultValue `false`
     */
    disableSelectedIcon?: boolean;
    /**
     * This should be the available `Option`s for the select to choose from. It
     * can also contain `OptGroup` or any other elements but only clicking on an
     * `Option` component will update the value.
     */
    children: ReactNode;
}
/**
 * **Client Component**
 *
 * @example Simple Example
 * ```tsx
 * import { Select, Option } from "react-md";
 * import { useState, type ReactElement } from "react";
 *
 * function Example(): ReactElement {
 *   const [value, setValue] = useState("");
 *
 *   return (
 *     <Select
 *       label="Select"
 *       value={value}
 *       onChange={(event) => setValue(event.currentTarget.value)}
 *       placeholder="Select a value"
 *     >
 *       <Option value="a">Option 1</Option>
 *       <Option value="b">Option 2</Option>
 *       <Option value="c">Option 3</Option>
 *       <Option value="d">Option 4</Option>
 *     </Select>
 *   );
 * }
 * ```
 *
 * @example Testing
 * ```tsx
 * rmdRender(
 *   <Select label="Select" selectedOptionProps={{ "data-testid": "selected" }}>
 *     <Option value="a">Option 1</Option>
 *     <Option value="b">Option 2</Option>
 *     <Option value="c">Option 3</Option>
 *     <Option value="d">Option 4</Option>
 *   </Select>
 * );
 *
 * const user = userEvent.setup();
 * const select = screen.getByRole("combobox", { name: "Select" });
 * const selected = screen.getByTestId("selected")
 * const selectInput = screen.getByRole("textbox", { hidden: true });
 * expect(selected).toHaveTextContent("");
 * expect(selectInput).toHaveValue("");
 *
 * await user.click(select);
 * await user.click(screen.getByRole("option"), { name: "Option 2" });
 *
 * expect(selected).toHaveTextContent("Option 2");
 * expect(selectInput).toHaveValue("b");
 * ```
 *
 * @since 6.0.0 Rewritten with a new API.
 */
export declare function Select<Value extends string>(props: RequireAtLeastOne<SelectProps<Value>, "label" | keyof LabelA11y>): ReactElement;
