text: import * as React from 'react';
  import PropTypes from 'prop-types';
  import clsx from 'clsx';
  import { chainPropTypes, integerPropType } from '@mui/utils';
  import {
    unstable_composeClasses as composeClasses,
    useAutocomplete,
    createFilterOptions,
  } from '@mui/core';
  import { alpha } from '@mui/system';
  import Popper from '../Popper';
  import ListSubheader from '../ListSubheader';
  import Paper from '../Paper';
  import IconButton from '../IconButton';
  import Chip from '../Chip';
  import inputClasses from '../Input/inputClasses';
  import inputBaseClasses from '../InputBase/inputBaseClasses';
  import outlinedInputClasses from '../OutlinedInput/outlinedInputClasses';
  import filledInputClasses from '../FilledInput/filledInputClasses';
  import ClearIcon from '../internal/svg-icons/Close';
  import ArrowDropDownIcon from '../internal/svg-icons/ArrowDropDown';
  import useThemeProps from '../styles/useThemeProps';
  import styled from '../styles/styled';
  import autocompleteClasses, { getAutocompleteUtilityClass } from './autocompleteClasses';
  import capitalize from '../utils/capitalize';
  
  const useUtilityClasses = (ownerState) => {
    const {
      classes,
      disablePortal,
      focused,
      fullWidth,
      hasClearIcon,
      hasPopupIcon,
      inputFocused,
      popupOpen,
      size,
    } = ownerState;
  
    const slots = {
      root: [
        'root',
        focused && 'focused',
        fullWidth && 'fullWidth',
        hasClearIcon && 'hasClearIcon',
        hasPopupIcon && 'hasPopupIcon',
      ],
      inputRoot: ['inputRoot'],
      input: ['input', inputFocused && 'inputFocused'],
      tag: ['tag', `tagSize${capitalize(size)}`],
      endAdornment: ['endAdornment'],
      clearIndicator: ['clearIndicator'],
      popupIndicator: ['popupIndicator', popupOpen && 'popupIndicatorOpen'],
      popper: ['popper', disablePortal && 'popperDisablePortal'],
      paper: ['paper'],
      listbox: ['listbox'],
      loading: ['loading'],
      noOptions: ['noOptions'],
      option: ['option'],
      groupLabel: ['groupLabel'],
      groupUl: ['groupUl'],
    };
  
    return composeClasses(slots, getAutocompleteUtilityClass, classes);
  };
  
  const AutocompleteRoot = styled('div', {
    name: 'MuiAutocomplete',
    slot: 'Root',
    overridesResolver: (props, styles) => {
      const { ownerState } = props;
      const { fullWidth, hasClearIcon, hasPopupIcon, inputFocused, size } = ownerState;
  
      return [
        { [`& .${autocompleteClasses.tag}`]: styles.tag },
        { [`& .${autocompleteClasses.tag}`]: styles[`tagSize${capitalize(size)}`] },
        { [`& .${autocompleteClasses.inputRoot}`]: styles.inputRoot },
        { [`& .${autocompleteClasses.input}`]: styles.input },
        { [`& .${autocompleteClasses.input}`]: inputFocused && styles.inputFocused },
        styles.root,
        fullWidth && styles.fullWidth,
        hasPopupIcon && styles.hasPopupIcon,
        hasClearIcon && styles.hasClearIcon,
      ];
    },
  })(({ ownerState }) => ({
    [`&.${autocompleteClasses.focused} .${autocompleteClasses.clearIndicator}`]: {
      visibility: 'visible',
    },
    /* Avoid double tap issue on iOS */
    '@media (pointer: fine)': {
      [`&:hover .${autocompleteClasses.clearIndicator}`]: {
        visibility: 'visible',
      },
    },
    ...(ownerState.fullWidth && {
      width: '100%',
    }),
    [`& .${autocompleteClasses.tag}`]: {
      margin: 3,
      maxWidth: 'calc(100% - 6px)',
      ...(ownerState.size === 'small' && {
        margin: 2,
        maxWidth: 'calc(100% - 4px)',
      }),
    },
    [`& .${autocompleteClasses.inputRoot}`]: {
      flexWrap: 'wrap',
      [`.${autocompleteClasses.hasPopupIcon}&, .${autocompleteClasses.hasClearIcon}&`]: {
        paddingRight: 26 + 4,
      },
      [`.${autocompleteClasses.hasPopupIcon}.${autocompleteClasses.hasClearIcon}&`]: {
        paddingRight: 52 + 4,
      },
      [`& .${autocompleteClasses.input}`]: {
        width: 0,
        minWidth: 30,
      },
    },
    [`& .${inputClasses.root}`]: {
      paddingBottom: 1,
      '& .MuiInput-input': {
        padding: '4px 4px 4px 0px',
      },
    },
    [`& .${inputClasses.root}.${inputBaseClasses.sizeSmall}`]: {
      [`& .${inputClasses.input}`]: {
        padding: '2px 4px 3px 0',
      },
    },
    [`& .${outlinedInputClasses.root}`]: {
      padding: 9,
      [`.${autocompleteClasses.hasPopupIcon}&, .${autocompleteClasses.hasClearIcon}&`]: {
        paddingRight: 26 + 4 + 9,
      },
      [`.${autocompleteClasses.hasPopupIcon}.${autocompleteClasses.hasClearIcon}&`]: {
        paddingRight: 52 + 4 + 9,
      },
      [`& .${autocompleteClasses.input}`]: {
        padding: '7.5px 4px 7.5px 6px',
      },
      [`& .${autocompleteClasses.endAdornment}`]: {
        right: 9,
      },
    },
    [`& .${outlinedInputClasses.root}.${inputBaseClasses.sizeSmall}`]: {
      padding: 6,
      [`& .${autocompleteClasses.input}`]: {
        padding: '2.5px 4px 2.5px 6px',
      },
    },
    [`& .${filledInputClasses.root}`]: {
      paddingTop: 19,
      paddingLeft: 8,
      [`.${autocompleteClasses.hasPopupIcon}&, .${autocompleteClasses.hasClearIcon}&`]: {
        paddingRight: 26 + 4 + 9,
      },
      [`.${autocompleteClasses.hasPopupIcon}.${autocompleteClasses.hasClearIcon}&`]: {
        paddingRight: 52 + 4 + 9,
      },
      [`& .${filledInputClasses.input}`]: {
        padding: '7px 4px',
      },
      [`& .${autocompleteClasses.endAdornment}`]: {
        right: 9,
      },
    },
    [`& .${filledInputClasses.root}.${inputBaseClasses.sizeSmall}`]: {
      paddingBottom: 1,
      [`& .${filledInputClasses.input}`]: {
        padding: '2.5px 4px',
      },
    },
    [`& .${autocompleteClasses.input}`]: {
      flexGrow: 1,
      textOverflow: 'ellipsis',
      opacity: 0,
      ...(ownerState.inputFocused && {
        opacity: 1,
      }),
    },
  }));
  
  const AutocompleteEndAdornment = styled('div', {
    name: 'MuiAutocomplete',
    slot: 'EndAdornment',
    overridesResolver: (props, styles) => styles.endAdornment,
  })({
    // We use a position absolute to support wrapping tags.
    position: 'absolute',
    right: 0,
    top: 'calc(50% - 14px)', // Center vertically
  });
  
  const AutocompleteClearIndicator = styled(IconButton, {
    name: 'MuiAutocomplete',
    slot: 'ClearIndicator',
    overridesResolver: (props, styles) => styles.clearIndicator,
  })({
    marginRight: -2,
    padding: 4,
    visibility: 'hidden',
  });
  
  const AutocompletePopupIndicator = styled(IconButton, {
    name: 'MuiAutocomplete',
    slot: 'PopupIndicator',
    overridesResolver: ({ ownerState }, styles) => ({
      ...styles.popupIndicator,
      ...(ownerState.popupOpen && styles.popupIndicatorOpen),
    }),
  })(({ ownerState }) => ({
    padding: 2,
    marginRight: -2,
    ...(ownerState.popupOpen && {
      transform: 'rotate(180deg)',
    }),
  }));
  
  const AutocompletePopper = styled(Popper, {
    name: 'MuiAutocomplete',
    slot: 'Popper',
    overridesResolver: (props, styles) => {
      const { ownerState } = props;
  
      return [
        { [`& .${autocompleteClasses.option}`]: styles.option },
        styles.popper,
        ownerState.disablePortal && styles.popperDisablePortal,
      ];
    },
  })(({ theme, ownerState }) => ({
    zIndex: theme.zIndex.modal,
    ...(ownerState.disablePortal && {
      position: 'absolute',
    }),
  }));
  
  const AutocompletePaper = styled(Paper, {
    name: 'MuiAutocomplete',
    slot: 'Paper',
    overridesResolver: (props, styles) => styles.paper,
  })(({ theme }) => ({
    ...theme.typography.body1,
    overflow: 'auto',
  }));
  
  const AutocompleteLoading = styled('div', {
    name: 'MuiAutocomplete',
    slot: 'Loading',
    overridesResolver: (props, styles) => styles.loading,
  })(({ theme }) => ({
    color: theme.palette.text.secondary,
    padding: '14px 16px',
  }));
  
  const AutocompleteNoOptions = styled('div', {
    name: 'MuiAutocomplete',
    slot: 'NoOptions',
    overridesResolver: (props, styles) => styles.noOptions,
  })(({ theme }) => ({
    color: theme.palette.text.secondary,
    padding: '14px 16px',
  }));
  
  const AutocompleteListbox = styled('div', {
    name: 'MuiAutocomplete',
    slot: 'Listbox',
    overridesResolver: (props, styles) => styles.listbox,
  })(({ theme }) => ({
    listStyle: 'none',
    margin: 0,
    padding: '8px 0',
    maxHeight: '40vh',
    overflow: 'auto',
    [`& .${autocompleteClasses.option}`]: {
      minHeight: 48,
      display: 'flex',
      overflow: 'hidden',
      justifyContent: 'flex-start',
      alignItems: 'center',
      cursor: 'pointer',
      paddingTop: 6,
      boxSizing: 'border-box',
      outline: '0',
      WebkitTapHighlightColor: 'transparent',
      paddingBottom: 6,
      paddingLeft: 16,
      paddingRight: 16,
      [theme.breakpoints.up('sm')]: {
        minHeight: 'auto',
      },
      [`&.${autocompleteClasses.focused}`]: {
        backgroundColor: theme.palette.action.hover,
        // Reset on touch devices, it doesn't add specificity
        '@media (hover: none)': {
          backgroundColor: 'transparent',
        },
      },
      '&[aria-disabled="true"]': {
        opacity: theme.palette.action.disabledOpacity,
        pointerEvents: 'none',
      },
      [`&.${autocompleteClasses.focusVisible}`]: {
        backgroundColor: theme.palette.action.focus,
      },
      '&[aria-selected="true"]': {
        backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
        [`&.${autocompleteClasses.focused}`]: {
          backgroundColor: alpha(
            theme.palette.primary.main,
            theme.palette.action.selectedOpacity + theme.palette.action.hoverOpacity,
          ),
          // Reset on touch devices, it doesn't add specificity
          '@media (hover: none)': {
            backgroundColor: theme.palette.action.selected,
          },
        },
        [`&.${autocompleteClasses.focusVisible}`]: {
          backgroundColor: alpha(
            theme.palette.primary.main,
            theme.palette.action.selectedOpacity + theme.palette.action.focusOpacity,
          ),
        },
      },
    },
  }));
  
  const AutocompleteGroupLabel = styled(ListSubheader, {
    name: 'MuiAutocomplete',
    slot: 'GroupLabel',
    overridesResolver: (props, styles) => styles.groupLabel,
  })(({ theme }) => ({
    backgroundColor: theme.palette.background.paper,
    top: -8,
  }));
  
  const AutocompleteGroupUl = styled('ul', {
    name: 'MuiAutocomplete',
    slot: 'GroupUl',
    overridesResolver: (props, styles) => styles.groupUl,
  })({
    padding: 0,
    [`& .${autocompleteClasses.option}`]: {
      paddingLeft: 24,
    },
  });
  
  export { createFilterOptions };
  
  const Autocomplete = React.forwardRef(function Autocomplete(inProps, ref) {
    const props = useThemeProps({ props: inProps, name: 'MuiAutocomplete' });
    /* eslint-disable @typescript-eslint/no-unused-vars */
    const {
      autoComplete = false,
      autoHighlight = false,
      autoSelect = false,
      blurOnSelect = false,
      ChipProps,
      className,
      clearIcon = <ClearIcon fontSize="small" />,
      clearOnBlur = !props.freeSolo,
      clearOnEscape = false,
      clearText = 'Clear',
      closeText = 'Close',
      componentsProps = {},
      defaultValue = props.multiple ? [] : null,
      disableClearable = false,
      disableCloseOnSelect = false,
      disabled = false,
      disabledItemsFocusable = false,
      disableListWrap = false,
      disablePortal = false,
      filterOptions,
      filterSelectedOptions = false,
      forcePopupIcon = 'auto',
      freeSolo = false,
      fullWidth = false,
      getLimitTagsText = (more) => `+${more}`,
      getOptionDisabled,
      getOptionLabel = (option) => option.label ?? option,
      isOptionEqualToValue,
      groupBy,
      handleHomeEndKeys = !props.freeSolo,
      id: idProp,
      includeInputInList = false,
      inputValue: inputValueProp,
      limitTags = -1,
      ListboxComponent = 'ul',
      ListboxProps,
      loading = false,
      loadingText = 'Loading…',
      multiple = false,
      noOptionsText = 'No options',
      onChange,
      onClose,
      onHighlightChange,
      onInputChange,
      onOpen,
      open,
      openOnFocus = false,
      openText = 'Open',
      options,
      PaperComponent = Paper,
      PopperComponent = Popper,
      popupIcon = <ArrowDropDownIcon />,
      renderGroup: renderGroupProp,
      renderInput,
      renderOption: renderOptionProp,
      renderTags,
      selectOnFocus = !props.freeSolo,
      size = 'medium',
      value: valueProp,
      ...other
    } = props;
    /* eslint-enable @typescript-eslint/no-unused-vars */
  
    const {
      getRootProps,
      getInputProps,
      getInputLabelProps,
      getPopupIndicatorProps,
      getClearProps,
      getTagProps,
      getListboxProps,
      getOptionProps,
      value,
      dirty,
      id,
      popupOpen,
      focused,
      focusedTag,
      anchorEl,
      setAnchorEl,
      inputValue,
      groupedOptions,
    } = useAutocomplete({ ...props, componentName: 'Autocomplete' });
  
    const hasClearIcon = !disableClearable && !disabled && dirty;
    const hasPopupIcon = (!freeSolo || forcePopupIcon === true) && forcePopupIcon !== false;
  
    const ownerState = {
      ...props,
      disablePortal,
      focused,
      fullWidth,
      hasClearIcon,
      hasPopupIcon,
      inputFocused: focusedTag === -1,
      popupOpen,
      size,
    };
  
    const classes = useUtilityClasses(ownerState);
  
    let startAdornment;
  
    if (multiple && value.length > 0) {
      const getCustomizedTagProps = (params) => ({
        className: clsx(classes.tag),
        disabled,
        ...getTagProps(params),
      });
  
      if (renderTags) {
        startAdornment = renderTags(value, getCustomizedTagProps);
      } else {
        startAdornment = value.map((option, index) => (
          <Chip
            label={getOptionLabel(option)}
            size={size}
            {...getCustomizedTagProps({ index })}
            {...ChipProps}
          />
        ));
      }
    }
  
    if (limitTags > -1 && Array.isArray(startAdornment)) {
      const more = startAdornment.length - limitTags;
      if (!focused && more > 0) {
        startAdornment = startAdornment.splice(0, limitTags);
        startAdornment.push(
          <span className={classes.tag} key={startAdornment.length}>
            {getLimitTagsText(more)}
          </span>,
        );
      }
    }
  
    const defaultRenderGroup = (params) => (
      <li key={params.key}>
        <AutocompleteGroupLabel
          className={classes.groupLabel}
          ownerState={ownerState}
          component="div"
        >
          {params.group}
        </AutocompleteGroupLabel>
        <AutocompleteGroupUl className={classes.groupUl} ownerState={ownerState}>
          {params.children}
        </AutocompleteGroupUl>
      </li>
    );
  
    const renderGroup = renderGroupProp || defaultRenderGroup;
    const defaultRenderOption = (props2, option) => <li {...props2}>{getOptionLabel(option)}</li>;
    const renderOption = renderOptionProp || defaultRenderOption;
  
    const renderListOption = (option, index) => {
      const optionProps = getOptionProps({ option, index });
  
      return renderOption({ ...optionProps, className: classes.option }, option, {
        selected: optionProps['aria-selected'],
        inputValue,
      });
    };
  
    return (
      <React.Fragment>
        <AutocompleteRoot
          ref={ref}
          className={clsx(classes.root, className)}
          ownerState={ownerState}
          {...getRootProps(other)}
        >
          {renderInput({
            id,
            disabled,
            fullWidth: true,
            size: size === 'small' ? 'small' : undefined,
            InputLabelProps: getInputLabelProps(),
            InputProps: {
              ref: setAnchorEl,
              className: classes.inputRoot,
              startAdornment,
              endAdornment: (
                <AutocompleteEndAdornment className={classes.endAdornment} ownerState={ownerState}>
                  {hasClearIcon ? (
                    <AutocompleteClearIndicator
                      {...getClearProps()}
                      aria-label={clearText}
                      title={clearText}
                      ownerState={ownerState}
                      {...componentsProps.clearIndicator}
                      className={clsx(
                        classes.clearIndicator,
                        componentsProps.clearIndicator?.className,
                      )}
                    >
                      {clearIcon}
                    </AutocompleteClearIndicator>
                  ) : null}
  
                  {hasPopupIcon ? (
                    <AutocompletePopupIndicator
                      {...getPopupIndicatorProps()}
                      disabled={disabled}
                      aria-label={popupOpen ? closeText : openText}
                      title={popupOpen ? closeText : openText}
                      className={clsx(classes.popupIndicator)}
                      ownerState={ownerState}
                    >
                      {popupIcon}
                    </AutocompletePopupIndicator>
                  ) : null}
                </AutocompleteEndAdornment>
              ),
            },
            inputProps: {
              className: clsx(classes.input),
              disabled,
              ...getInputProps(),
            },
          })}
        </AutocompleteRoot>
        {popupOpen && anchorEl ? (
          <AutocompletePopper
            as={PopperComponent}
            className={clsx(classes.popper)}
            disablePortal={disablePortal}
            style={{
              width: anchorEl ? anchorEl.clientWidth : null,
            }}
            ownerState={ownerState}
            role="presentation"
            anchorEl={anchorEl}
            open
          >
            <AutocompletePaper as={PaperComponent} className={classes.paper} ownerState={ownerState}>
              {loading && groupedOptions.length === 0 ? (
                <AutocompleteLoading className={classes.loading} ownerState={ownerState}>
                  {loadingText}
                </AutocompleteLoading>
              ) : null}
              {groupedOptions.length === 0 && !freeSolo && !loading ? (
                <AutocompleteNoOptions
                  className={classes.noOptions}
                  ownerState={ownerState}
                  role="presentation"
                  onMouseDown={(event) => {
                    // Prevent input blur when interacting with the "no options" content
                    event.preventDefault();
                  }}
                >
                  {noOptionsText}
                </AutocompleteNoOptions>
              ) : null}
              {groupedOptions.length > 0 ? (
                <AutocompleteListbox
                  as={ListboxComponent}
                  className={classes.listbox}
                  ownerState={ownerState}
                  {...getListboxProps()}
                  {...ListboxProps}
                >
                  {groupedOptions.map((option, index) => {
                    if (groupBy) {
                      return renderGroup({
                        key: option.key,
                        group: option.group,
                        children: option.options.map((option2, index2) =>
                          renderListOption(option2, option.index + index2),
                        ),
                      });
                    }
                    return renderListOption(option, index);
                  })}
                </AutocompleteListbox>
              ) : null}
            </AutocompletePaper>
          </AutocompletePopper>
        ) : null}
      </React.Fragment>
    );
  });
  
  Autocomplete.propTypes /* remove-proptypes */ = {
    // ----------------------------- Warning --------------------------------
    // | These PropTypes are generated from the TypeScript type definitions |
    // |     To update them edit the d.ts file and run "yarn proptypes"     |
    // ----------------------------------------------------------------------
    /**
     * If `true`, the portion of the selected suggestion that has not been typed by the user,
     * known as the completion string, appears inline after the input cursor in the textbox.
     * The inline completion string is visually highlighted and has a selected state.
     * @default false
     */
    autoComplete: PropTypes.bool,
    /**
     * If `true`, the first option is automatically highlighted.
     * @default false
     */
    autoHighlight: PropTypes.bool,
    /**
     * If `true`, the selected option becomes the value of the input
     * when the Autocomplete loses focus unless the user chooses
     * a different option or changes the character string in the input.
     * @default false
     */
    autoSelect: PropTypes.bool,
    /**
     * Control if the input should be blurred when an option is selected:
     *
     * - `false` the input is not blurred.
     * - `true` the input is always blurred.
     * - `touch` the input is blurred after a touch event.
     * - `mouse` the input is blurred after a mouse event.
     * @default false
     */
    blurOnSelect: PropTypes.oneOfType([PropTypes.oneOf(['mouse', 'touch']), PropTypes.bool]),
    /**
     * Props applied to the [`Chip`](/api/chip/) element.
     */
    ChipProps: PropTypes.object,
    /**
     * Override or extend the styles applied to the component.
     */
    classes: PropTypes.object,
    /**
     * @ignore
     */
    className: PropTypes.string,
    /**
     * The icon to display in place of the default clear icon.
     * @default <ClearIcon fontSize="small" />
     */
    clearIcon: PropTypes.node,
    /**
     * If `true`, the input's text is cleared on blur if no value is selected.
     *
     * Set to `true` if you want to help the user enter a new value.
     * Set to `false` if you want to help the user resume his search.
     * @default !props.freeSolo
     */
    clearOnBlur: PropTypes.bool,
    /**
     * If `true`, clear all values when the user presses escape and the popup is closed.
     * @default false
     */
    clearOnEscape: PropTypes.bool,
    /**
     * Override the default text for the *clear* icon button.
     *
     * For localization purposes, you can use the provided [translations](/guides/localization/).
     * @default 'Clear'
     */
    clearText: PropTypes.string,
    /**
     * Override the default text for the *close popup* icon button.
     *
     * For localization purposes, you can use the provided [translations](/guides/localization/).
     * @default 'Close'
     */
    closeText: PropTypes.string,
    /**
     * The props used for each slot inside.
     * @default {}
     */
    componentsProps: PropTypes.object,
    /**
     * The default value. Use when the component is not controlled.
     * @default props.multiple ? [] : null
     */
    defaultValue: chainPropTypes(PropTypes.any, (props) => {
      if (props.multiple && props.defaultValue !== undefined && !Array.isArray(props.defaultValue)) {
        return new Error(
          [
            'MUI: The Autocomplete expects the `defaultValue` prop to be an array when `multiple={true}` or undefined.',
            `However, ${props.defaultValue} was provided.`,
          ].join('\n'),
        );
      }
      return null;
    }),
    /**
     * If `true`, the input can't be cleared.
     * @default false
     */
    disableClearable: PropTypes.bool,
    /**
     * If `true`, the popup won't close when a value is selected.
     * @default false
     */
    disableCloseOnSelect: PropTypes.bool,
    /**
     * If `true`, the component is disabled.
     * @default false
     */
    disabled: PropTypes.bool,
    /**
     * If `true`, will allow focus on disabled items.
     * @default false
     */
    disabledItemsFocusable: PropTypes.bool,
    /**
     * If `true`, the list box in the popup will not wrap focus.
     * @default false
     */
    disableListWrap: PropTypes.bool,
    /**
     * If `true`, the `Popper` content will be under the DOM hierarchy of the parent component.
     * @default false
     */
    disablePortal: PropTypes.bool,
    /**
     * A filter function that determines the options that are eligible.
     *
     * @param {T[]} options The options to render.
     * @param {object} state The state of the component.
     * @returns {T[]}
     */
    filterOptions: PropTypes.func,
    /**
     * If `true`, hide the selected options from the list box.
     * @default false
     */
    filterSelectedOptions: PropTypes.bool,
    /**
     * Force the visibility display of the popup icon.
     * @default 'auto'
     */
    forcePopupIcon: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.bool]),
    /**
     * If `true`, the Autocomplete is free solo, meaning that the user input is not bound to provided options.
     * @default false
     */
    freeSolo: PropTypes.bool,
    /**
     * If `true`, the input will take up the full width of its container.
     * @default false
     */
    fullWidth: PropTypes.bool,
    /**
     * The label to display when the tags are truncated (`limitTags`).
     *
     * @param {number} more The number of truncated tags.
     * @returns {ReactNode}
     * @default (more) => `+${more}`
     */
    getLimitTagsText: PropTypes.func,
    /**
     * Used to determine the disabled state for a given option.
     *
     * @param {T} option The option to test.
     * @returns {boolean}
     */
    getOptionDisabled: PropTypes.func,
    /**
     * Used to determine the string value for a given option.
     * It's used to fill the input (and the list box options if `renderOption` is not provided).
     *
     * @param {T} option
     * @returns {string}
     * @default (option) => option.label ?? option
     */
    getOptionLabel: PropTypes.func,
    /**
     * If provided, the options will be grouped under the returned string.
     * The groupBy value is also used as the text for group headings when `renderGroup` is not provided.
     *
     * @param {T} options The options to group.
     * @returns {string}
     */
    groupBy: PropTypes.func,
    /**
     * If `true`, the component handles the "Home" and "End" keys when the popup is open.
     * It should move focus to the first option and last option, respectively.
     * @default !props.freeSolo
     */
    handleHomeEndKeys: PropTypes.bool,
    /**
     * This prop is used to help implement the accessibility logic.
     * If you don't provide an id it will fall back to a randomly generated one.
     */
    id: PropTypes.string,
    /**
     * If `true`, the highlight can move to the input.
     * @default false
     */
    includeInputInList: PropTypes.bool,
    /**
     * The input value.
     */
    inputValue: PropTypes.string,
    /**
     * Used to determine if the option represents the given value.
     * Uses strict equality by default.
     * ⚠️ Both arguments need to be handled, an option can only match with one value.
     *
     * @param {T} option The option to test.
     * @param {T} value The value to test against.
     * @returns {boolean}
     */
    isOptionEqualToValue: PropTypes.func,
    /**
     * The maximum number of tags that will be visible when not focused.
     * Set `-1` to disable the limit.
     * @default -1
     */
    limitTags: integerPropType,
    /**
     * The component used to render the listbox.
     * @default 'ul'
     */
    ListboxComponent: PropTypes.elementType,
    /**
     * Props applied to the Listbox element.
     */
    ListboxProps: PropTypes.object,
    /**
     * If `true`, the component is in a loading state.
     * This shows the `loadingText` in place of suggestions (only if there are no suggestions to show, e.g. `options` are empty).
     * @default false
     */
    loading: PropTypes.bool,
    /**
     * Text to display when in a loading state.
     *
     * For localization purposes, you can use the provided [translations](/guides/localization/).
     * @default 'Loading…'
     */
    loadingText: PropTypes.node,
    /**
     * If `true`, `value` must be an array and the menu will support multiple selections.
     * @default false
     */
    multiple: PropTypes.bool,
    /**
     * Text to display when there are no options.
     *
     * For localization purposes, you can use the provided [translations](/guides/localization/).
     * @default 'No options'
     */
    noOptionsText: PropTypes.node,
    /**
     * Callback fired when the value changes.
     *
     * @param {React.SyntheticEvent} event The event source of the callback.
     * @param {T|T[]} value The new value of the component.
     * @param {string} reason One of "createOption", "selectOption", "removeOption", "blur" or "clear".
     * @param {string} [details]
     */
    onChange: PropTypes.func,
    /**
     * Callback fired when the popup requests to be closed.
     * Use in controlled mode (see open).
     *
     * @param {React.SyntheticEvent} event The event source of the callback.
     * @param {string} reason Can be: `"toggleInput"`, `"escape"`, `"selectOption"`, `"removeOption"`, `"blur"`.
     */
    onClose: PropTypes.func,
    /**
     * Callback fired when the highlight option changes.
     *
     * @param {React.SyntheticEvent} event The event source of the callback.
     * @param {T} option The highlighted option.
     * @param {string} reason Can be: `"keyboard"`, `"auto"`, `"mouse"`.
     */
    onHighlightChange: PropTypes.func,
    /**
     * Callback fired when the input value changes.
     *
     * @param {React.SyntheticEvent} event The event source of the callback.
     * @param {string} value The new value of the text input.
     * @param {string} reason Can be: `"input"` (user input), `"reset"` (programmatic change), `"clear"`.
     */
    onInputChange: PropTypes.func,
    /**
     * Callback fired when the popup requests to be opened.
     * Use in controlled mode (see open).
     *
     * @param {React.SyntheticEvent} event The event source of the callback.
     */
    onOpen: PropTypes.func,
    /**
     * If `true`, the component is shown.
     */
    open: PropTypes.bool,
    /**
     * If `true`, the popup will open on input focus.
     * @default false
     */
    openOnFocus: PropTypes.bool,
    /**
     * Override the default text for the *open popup* icon button.
     *
     * For localization purposes, you can use the provided [translations](/guides/localization/).
     * @default 'Open'
     */
    openText: PropTypes.string,
    /**
     * Array of options.
     */
    options: PropTypes.array.isRequired,
    /**
     * The component used to render the body of the popup.
     * @default Paper
     */
    PaperComponent: PropTypes.elementType,
    /**
     * The component used to position the popup.
     * @default Popper
     */
    PopperComponent: PropTypes.elementType,
    /**
     * The icon to display in place of the default popup icon.
     * @default <ArrowDropDownIcon />
     */
    popupIcon: PropTypes.node,
    /**
     * Render the group.
     *
     * @param {AutocompleteRenderGroupParams} params The group to render.
     * @returns {ReactNode}
     */
    renderGroup: PropTypes.func,
    /**
     * Render the input.
     *
     * @param {object} params
     * @returns {ReactNode}
     */
    renderInput: PropTypes.func.isRequired,
    /**
     * Render the option, use `getOptionLabel` by default.
     *
     * @param {object} props The props to apply on the li element.
     * @param {T} option The option to render.
     * @param {object} state The state of the component.
     * @returns {ReactNode}
     */
    renderOption: PropTypes.func,
    /**
     * Render the selected value.
     *
     * @param {T[]} value The `value` provided to the component.
     * @param {function} getTagProps A tag props getter.
     * @returns {ReactNode}
     */
    renderTags: PropTypes.func,
    /**
     * If `true`, the input's text is selected on focus.
     * It helps the user clear the selected value.
     * @default !props.freeSolo
     */
    selectOnFocus: PropTypes.bool,
    /**
     * The size of the component.
     * @default 'medium'
     */
    size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
      PropTypes.oneOf(['small', 'medium']),
      PropTypes.string,
    ]),
    /**
     * The system prop that allows defining system overrides as well as additional CSS styles.
     */
    sx: PropTypes.oneOfType([
      PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object])),
      PropTypes.func,
      PropTypes.object,
    ]),
    /**
     * The value of the autocomplete.
     *
     * The value must have reference equality with the option in order to be selected.
     * You can customize the equality behavior with the `isOptionEqualToValue` prop.
     */
    value: chainPropTypes(PropTypes.any, (props) => {
      if (props.multiple && props.value !== undefined && !Array.isArray(props.value)) {
        return new Error(
          [
            'MUI: The Autocomplete expects the `value` prop to be an array when `multiple={true}` or undefined.',
            `However, ${props.value} was provided.`,
          ].join('\n'),
        );
      }
      return null;
    }),
  };
  
  export default Autocomplete;
  