# All files / autocomplete AutocompleteGeneric.tsx

0% Statements 0/73
0% Branches 0/1
0% Functions 0/1
0% Lines 0/73

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

     "use client";
    import { useMemo, type ReactElement } from "react";
    import { Option } from "../form/Option.js";
    import { TextField, type TextFieldProps } from "../form/TextField.js";
    import {
      ListboxProvider,
      type ListboxContext,
    } from "../form/useListboxProvider.js";
    import { Menu } from "../menu/Menu.js";
    import { KeyboardMovementProvider } from "../movement/useKeyboardMovementProvider.js";
    import { type ProvidedAutocompleteProps } from "./useAutocompleteAgain.js";
    import { type ConfigurableComboboxMenuProps } from "../form/useCombobox.js";

    export interface AutocompleteGenericProps<T>
      extends Omit<TextFieldProps, keyof ProvidedAutocompleteProps<T>>,
        ProvidedAutocompleteProps<T> {
      menuProps?: ConfigurableComboboxMenuProps;
    }

    export function AutocompleteGeneric<T>(
      props: AutocompleteGenericProps<T>
    ): ReactElement {
      const {
        movementContext,
        comboboxRef,
        getMenuProps,
        suggestions,
        menuProps,
        ...remaining
      } = props;
      const listboxContext = useMemo<ListboxContext>(
        () => ({
          inputRef: comboboxRef,
          currentValue: null,
          selectedIconAfter: false,
          disableSelectedIcon: true,
        }),
        [comboboxRef]
      );
      return (
        <KeyboardMovementProvider value={movementContext}>
          <TextField {...remaining} ref={comboboxRef} />
          <Menu aria-label="Options" {...getMenuProps(menuProps)}>
            <ListboxProvider value={listboxContext}>
              {suggestions.map((suggestion) => {
                let value: string;
                let label: string;
                if (typeof suggestion === "string") {
                  label = suggestion;
                  value = suggestion;
                } else if (
                  typeof suggestion === "object" &&
                  suggestion &&
                  "label" in suggestion &&
                  typeof suggestion.label === "string"
                ) {
                  label = suggestion.label;
                  value = label;
                } else {
                  throw new Error();
                }

                return (
                  <Option key={value} value={label}>
                    {label}
                  </Option>
                );
              })}
            </ListboxProvider>
          </Menu>
        </KeyboardMovementProvider>
      );
    }