text: var __rest = (this && this.__rest) || function (s, e) {
      var t = {};
      for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
          t[p] = s[p];
      if (s != null && typeof Object.getOwnPropertySymbols === "function")
          for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
              if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                  t[p[i]] = s[p[i]];
          }
      return t;
  };
  import { CloseIcon } from '@sanity/icons';
  import React, { cloneElement, forwardRef, useCallback, useEffect, useRef, useState } from 'react';
  import styled from 'styled-components';
  import { focusFirstDescendant } from '../../helpers';
  import { useForwardedRef } from '../../hooks';
  import { Box, Button, Card, Spinner, Text, TextInput } from '../../primitives';
  import { getResponsiveProp } from '../../styles';
  import { AutocompleteOption } from './autocompleteOption';
  import { Root, LoadingCard, ListBoxContainer, ListBoxCard } from './styles';
  const ClearButtonBox = styled(Box) `
    position: absolute;
    top: 0;
    right: 0;
    z-index: 1;
  
    & > button {
      vertical-align: top;
    }
  `;
  const defaultRenderOption = ({ value }) => (React.createElement(Card, { as: "button", padding: 3 },
      React.createElement(Text, null, value)));
  const defaultRenderValue = (value, option) => option ? option.value : value;
  const defaultFilterOption = (query, option) => option.value.toLowerCase().indexOf(query.toLowerCase()) > -1;
  const LIST_IGNORE_KEYS = [
      'Control',
      'Shift',
      'Alt',
      'Enter',
      'Home',
      'End',
      'PageUp',
      'PageDown',
      'Meta',
      'Tab',
      'CapsLock',
  ];
  const InnerAutocomplete = forwardRef((props, ref) => {
      const { border = true, filterOption: filterOptionProp, fontSize = 2, icon, id, loading, onChange, onQueryChange, onSelect, options: optionsProp = [], padding: paddingProp = 3, radius = 2, renderOption: renderOptionProp, renderValue = defaultRenderValue, value: valueProp = '' } = props, restProps = __rest(props, ["border", "filterOption", "fontSize", "icon", "id", "loading", "onChange", "onQueryChange", "onSelect", "options", "padding", "radius", "renderOption", "renderValue", "value"]);
      const renderOption = typeof renderOptionProp === 'function' ? renderOptionProp : defaultRenderOption;
      const filterOption = typeof filterOptionProp === 'function' ? filterOptionProp : defaultFilterOption;
      const [value, setValue] = useState(valueProp);
      const [query, setQuery] = useState(null);
      const valueRef = useRef(value);
      const [focused, setFocused] = useState(false);
      const listboxId = `${id}-listbox`;
      const options = Array.isArray(optionsProp) ? optionsProp : [];
      const [selectedIndex, setSelectedIndex] = useState(-1);
      const inputRef = useRef(null);
      const listRef = useRef(null);
      const activeItemId = selectedIndex > -1 ? `${id}-option-${selectedIndex}` : undefined;
      const padding = getResponsiveProp(paddingProp);
      const rootRef = useRef(null);
      const currentOption = value ? options.find((o) => o.value === value) : undefined;
      const filteredOptions = options.filter((option) => (query ? filterOption(query, option) : true));
      const optionsLen = filteredOptions.length;
      const expanded = loading || (focused && optionsLen > 0 && query !== null);
      const forwardedRef = useForwardedRef(ref);
      const handleRootBlur = useCallback(() => {
          setTimeout(() => {
              const rootEl = rootRef.current;
              const focusedEl = document.activeElement;
              const focusInside = rootEl && focusedEl && rootEl.contains(focusedEl);
              if (!focusInside)
                  setFocused(false);
          }, 0);
      }, []);
      const handleRootKeyDown = useCallback((event) => {
          var _a, _b;
          if (event.key === 'ArrowDown') {
              event.preventDefault();
              if (!optionsLen)
                  return;
              setSelectedIndex((index) => (index + 1) % optionsLen);
              return;
          }
          if (event.key === 'ArrowUp') {
              event.preventDefault();
              if (!optionsLen)
                  return;
              setSelectedIndex((index) => {
                  return index === -1 ? optionsLen - 1 : (optionsLen + index - 1) % optionsLen;
              });
              return;
          }
          if (event.key === 'Escape') {
              setFocused(false);
              valueRef.current = '';
              setQuery(null);
              if (onQueryChange)
                  onQueryChange(null);
              (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
              return;
          }
          const target = event.target;
          const listEl = listRef.current;
          if ((listEl === target || (listEl === null || listEl === void 0 ? void 0 : listEl.contains(target))) &&
              !LIST_IGNORE_KEYS.includes(event.key)) {
              (_b = inputRef.current) === null || _b === void 0 ? void 0 : _b.focus();
              return;
          }
      }, [onQueryChange, optionsLen]);
      const handleInputChange = useCallback((event) => {
          const q = event.currentTarget.value;
          valueRef.current = q;
          setQuery(q);
          if (onQueryChange)
              onQueryChange(q);
      }, [onQueryChange]);
      const handleInputFocus = useCallback(() => setFocused(true), []);
      const handleClearButtonClick = useCallback(() => {
          var _a;
          valueRef.current = '';
          setValue('');
          if (onChange)
              onChange('');
          setQuery(null);
          if (onQueryChange)
              onQueryChange(null);
          (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
      }, [onChange, onQueryChange]);
      const handleClearButtonFocus = useCallback(() => setFocused(true), []);
      const handleOptionSelect = useCallback((v) => {
          var _a;
          if (onSelect)
              onSelect(v);
          setValue(v);
          if (onChange)
              onChange(v);
          setQuery(null);
          if (onQueryChange)
              onQueryChange(null);
          setFocused(false);
          (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
      }, [onChange, onSelect, onQueryChange]);
      // Change the value when `value` prop changes
      useEffect(() => {
          if (valueProp !== valueRef.current) {
              valueRef.current = valueProp;
              setValue(valueProp);
          }
      }, [valueProp]);
      // Reset selected item when the list changes
      // @todo: what if the list changed, but the items have changed?
      useEffect(() => setSelectedIndex(-1), [optionsLen]);
      // Focus the selected item
      useEffect(() => {
          const listElement = listRef.current;
          if (!listElement)
              return;
          const selectedItemElement = listElement.childNodes[selectedIndex];
          if (selectedItemElement) {
              focusFirstDescendant(selectedItemElement);
          }
      }, [selectedIndex]);
      const setRef = (el) => {
          inputRef.current = el;
          forwardedRef.current = el;
      };
      return (React.createElement(Root, { "data-ui": "Autocomplete", onBlur: handleRootBlur, onKeyDown: handleRootKeyDown, ref: rootRef },
          React.createElement(TextInput, Object.assign({}, restProps, { "aria-activedescendant": activeItemId, "aria-autocomplete": "list", "aria-expanded": expanded, "aria-owns": listboxId, autoCapitalize: "off", autoComplete: "off", autoCorrect: "off", border: border, icon: icon, id: id, inputMode: "search", onChange: handleInputChange, onFocus: handleInputFocus, padding: padding, radius: radius, ref: setRef, role: "combobox", fontSize: fontSize, spellCheck: false, value: query === null ? renderValue(value, currentOption) : query })),
          value.length > 0 && (React.createElement(ClearButtonBox, { margin: padding.map((v) => v - 1), onFocus: handleClearButtonFocus },
              React.createElement(Button, { "aria-label": "Clear", "data-qa": "clear-button", fontSize: fontSize, icon: CloseIcon, mode: "bleed", onClick: handleClearButtonClick, padding: padding.map((v) => v - 2) }))),
          React.createElement(ListBoxContainer, { hidden: !expanded },
              React.createElement(ListBoxCard, { paddingY: 1, radius: 1, shadow: 2, tabIndex: -1 },
                  React.createElement("ul", { "aria-multiselectable": false, id: listboxId, ref: listRef, role: "listbox" }, filteredOptions.map((option, optionIndex) => (React.createElement(AutocompleteOption, { id: `${id}-option-${optionIndex}`, key: optionIndex, onSelect: handleOptionSelect, selected: selectedIndex > -1 ? optionIndex === selectedIndex : currentOption === option, value: option.value }, cloneElement(renderOption(option), { disabled: loading, tabIndex: -1 }))))),
                  React.createElement(LoadingCard, { padding: 3, style: { opacity: loading ? 0.5 : 0 } },
                      React.createElement(Spinner, null))))));
  });
  InnerAutocomplete.displayName = 'Autocomplete';
  export const Autocomplete = InnerAutocomplete;
  //# sourceMappingURL=autocomplete.js.map