# All files / autocomplete FilterAutocompleteOptions.tsx

97.84% Statements 91/93
66.66% Branches 8/12
66.66% Functions 2/3
97.84% Lines 91/93

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    941x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x

    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    72x
    47x
    15x
    15x
    32x
    32x
    32x
    32x
    32x
    32x
    32x
    72x
    72x
    72x
    72x
    72x
    72x
    459x
    459x
    459x
    459x
    459x
    459x
    459x
    459x
    459x
    459x
    459x
    459x
    459x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    459x
    459x
    459x
    459x
    459x
    72x
    72x
    72x
     "use client";
    import { useMemo, type ReactElement, type RefObject } from "react";
    import {
      triggerManualChangeEvent,
      type EditableHTMLElement,
    } from "../form/utils.js";
    import { ListSubheader } from "../list/ListSubheader.js";
    import { MenuItem } from "../menu/MenuItem.js";
    import {
      defaultAutocompleteExtractor,
      defaultAutocompleteFilter,
      defaultAutocompleteOptionProps,
    } from "./defaults.js";
    import { type AutocompleteOptionsProps } from "./types.js";

    const noop = (): void => {
      // do nothing
    };

    const DEFAULT_NO_OPTIONS = <ListSubheader>No Options</ListSubheader>;

    export interface FilterAutocompleteOptionsProps<T>
      extends AutocompleteOptionsProps<T> {
      query: string;
      comboboxRef: RefObject<EditableHTMLElement>;
      selection: T | null;
      setSelection(selection: T | null): void;
    }

    export function FilterAutocompleteOptions<T>(
      props: FilterAutocompleteOptionsProps<T>
    ): ReactElement {
      const {
        query,
        filter = defaultAutocompleteFilter,
        options,
        extractor = defaultAutocompleteExtractor,
        whitespace = "keep",
        selection,
        setSelection,
        comboboxRef,
        disableFilter,
        getOptionProps = defaultAutocompleteOptionProps,
        clearOnAutocomplete,
        noOptionsChildren = DEFAULT_NO_OPTIONS,
      } = props;

      const filtered = useMemo(() => {
        if (disableFilter) {
          return options;
        }

        return filter({
          list: options,
          query,
          extractor,
          whitespace,
        });
      }, [disableFilter, extractor, filter, options, query, whitespace]);

      return (
        <>
          {!filtered.length && noOptionsChildren}
          {filtered.map((option, index) => {
            const label = extractor(option);
            const optionProps = getOptionProps({
              index,
              option,
            });

            return (
              <MenuItem
                aria-selected={selection === option || undefined}
                key={label}
                role="option"
                {...optionProps}
                onClick={(event) => {
                  optionProps?.onClick?.(event);

                  triggerManualChangeEvent(
                    comboboxRef.current,
                    clearOnAutocomplete ? "" : label
                  );
                  setSelection(option);
                }}
              >
                {optionProps?.children ?? label}
              </MenuItem>
            );
          })}
        </>
      );
    }