Repository: adobe/react-spectrum
File: packages/@react-aria/autocomplete/src/useAutocomplete.ts (TypeScript)

Code before:
   */
  disableAutoFocusFirst?: boolean,

  /**
   * Whether the autocomplete should disable virtual focus, instead making the wrapped collection directly tabbable.
   * @default false
   */
  disableVirtualFocus?: boolean
}

export interface AriaAutocompleteOptions<T> extends Omit<AriaAutocompleteProps<T>, 'children'> {
  /** The ref for the wrapped collection element. */
  inputRef: RefObject<HTMLInputElement | null>,
  /** The ref for the wrapped collection element. */
  collectionRef: RefObject<HTMLElement | null>
}

export interface AutocompleteAria<T> {
  /** Props for the autocomplete textfield/searchfield element. These should be passed to the textfield/searchfield aria hooks respectively. */
  textFieldProps: AriaTextFieldProps<FocusableElement>,
  /** Props for the collection, to be passed to collection's respective aria hook (e.g. useMenu). */
  collectionProps: CollectionOptions,
  /** Ref to attach to the wrapped collection. */
  collectionRef: RefObject<HTMLElement | null>,
  /** A filter function that returns if the provided collection node should be filtered out of the collection. */
  filter?: (nodeTextValue: string, node: Node<T>) => boolean
}

/**
 * Provides the behavior and accessibility implementation for an autocomplete component.
 * An autocomplete combines a text input with a collection, allowing users to filter the collection's contents match a query.
 * @param props - Props for the autocomplete.
 * @param state - State for the autocomplete, as returned by `useAutocompleteState`.
 */
export function useAutocomplete<T>(props: AriaAutocompleteOptions<T>, state: AutocompleteState): AutocompleteAria<T> {
  let {
    inputRef,
    collectionRef,
    filter,
    disableAutoFocusFirst = false,
    disableVirtualFocus = false
  } = props;

  let collectionId = useSlotId();
  let timeout = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
  let delayNextActiveDescendant = useRef(false);
  let queuedActiveDescendant = useRef<string | null>(null);
  let lastCollectionNode = useRef<HTMLElement>(null);

  // For mobile screen readers, we don't want virtual focus, instead opting to disable FocusScope's restoreFocus and manually
  // moving focus back to the subtriggers

Review comment (suggestion):
brings up more in line with how we've named this in other hooks and narrows the type to match `FieldInputContext`. 

Code after:
  filter?: (textValue: string, inputValue: string, node: Node<T>) => boolean,

  /**
   * Whether or not to focus the first item in the collection after a filter is performed. Note this is only applicable
   * if virtual focus behavior is not turned off via `disableVirtualFocus`.
   * @default false
   */
  disableAutoFocusFirst?: boolean,

  /**
   * Whether the autocomplete should disable virtual focus, instead making the wrapped collection directly tabbable.
   * @default false
   */
  disableVirtualFocus?: boolean
}

export interface AriaAutocompleteOptions<T> extends Omit<AriaAutocompleteProps<T>, 'children'> {
  /** The ref for the wrapped collection element. */
  inputRef: RefObject<HTMLInputElement | null>,
  /** The ref for the wrapped collection element. */
  collectionRef: RefObject<HTMLElement | null>
}

export interface AutocompleteAria<T> {
  /** Props for the autocomplete input element. These should be passed to the input's aria hooks (e.g. useTextField/useSearchField/etc) respectively. */
  inputProps: InputProps,
  /** Props for the collection, to be passed to collection's respective aria hook (e.g. useMenu). */
  collectionProps: CollectionOptions,
  /** Ref to attach to the wrapped collection. */
  collectionRef: RefObject<HTMLElement | null>,
  /** A filter function that returns if the provided collection node should be filtered out of the collection. */
  filter?: (nodeTextValue: string, node: Node<T>) => boolean
}

/**
 * Provides the behavior and accessibility implementation for an autocomplete component.
 * An autocomplete combines a text input with a collection, allowing users to filter the collection's contents match a query.
 * @param props - Props for the autocomplete.
 * @param state - State for the autocomplete, as returned by `useAutocompleteState`.
 */
export function useAutocomplete<T>(props: AriaAutocompleteOptions<T>, state: AutocompleteState): AutocompleteAria<T> {
  let {
    inputRef,
    collectionRef,
    filter,
    disableAutoFocusFirst = false,
    disableVirtualFocus = false
  } = props;

  let collectionId = useSlotId();
  let timeout = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);