import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import { forwardRef, useRef, useId, useState, useMemo, useCallback, useEffect } from 'react';
import { S as SelectOptions } from './SelectOptions-BIVTviOh.js';
import { O as OptionsDialog, a as OptionsPopover } from './useAdaptiveView-AvsDkChF.js';
import { M as MenuFooter } from './MenuFooter-Ck9L599M.js';
import { u as useSelectOrchestration, a as useProcessedOptions, b as buildSelectItems, s as shouldShowAddNewItem, A as AddNewItemButton, d as defaultSyncFilter, t as toSyncFilterFn, c as sortByGroup } from './syncFilterUtils-BVclVovw.js';
import { u as useMenuInteraction } from './useMenuInteraction-NEJXUD4I.js';
import { u as useDebouncedCallback } from './useDebouncedCallback-DLkapjcP.js';
import { S as SearchField } from './SearchField-B7fIOJf-.js';

const SelectMenu = forwardRef(
  (props, ref) => {
    const triggerRef = useRef(null);
    const searchRef = useRef(null);
    const {
      id: idProp,
      value: selectedOption,
      initialLoad: initialLoadProp,
      displayMenuAs: displayMenuAsProp,
      lazy,
      loadOptions: loadOptionsProp,
      label,
      searchPlaceholder,
      debounceMs = 200,
      onSelectedOptionChange,
      cache,
      pinned,
      virtualize,
      disableSearch,
      popoverWidth,
      trigger,
      onSearchChange,
      onMenuKeyDown,
      onImplicitClose,
      onExplicitClose,
      addItemLabel,
      onAddNewItem,
      clear
    } = props;
    const groupToString = "groupToString" in props ? props.groupToString : void 0;
    const groupSorter = "groupSorter" in props ? props.groupSorter : void 0;
    const autoId = useId();
    const id = idProp ?? autoId;
    const {
      displayAs,
      initialLoad,
      initialLoadPerformed,
      setInitialLoadPerformed,
      options,
      loading,
      loadingMore,
      hasMore,
      loadOptions,
      loadMore
    } = useSelectOrchestration({
      lazy,
      loadOptions: loadOptionsProp,
      cache,
      lazyOptions: "lazyOptions" in props ? props.lazyOptions : void 0,
      initialLoad: initialLoadProp,
      displayMenuAs: displayMenuAsProp,
      ref
    });
    const [inputValue, setInputValue] = useState("");
    const searchValue = disableSearch ? "" : inputValue;
    const { pinnedSections, ungroupedItems, groupSections } = useProcessedOptions({
      options,
      pinned,
      searchValue,
      groupToString,
      groupSorter
    });
    const { items, sectionsMeta } = useMemo(
      () => buildSelectItems({
        pinnedSections,
        groupSections,
        ungroupedItems
      }),
      [pinnedSections, groupSections, ungroupedItems]
    );
    const selectedItemIds = useMemo(
      () => new Set(selectedOption ? [selectedOption.id] : []),
      [selectedOption]
    );
    const handleItemActivate = useCallback(
      (item) => {
        if (item.type === "option" || item.type === "pinned-option" || item.type === "grouped-option") {
          onSelectedOptionChange(item.original);
        } else {
          onSelectedOptionChange(null);
        }
      },
      [onSelectedOptionChange]
    );
    const [isOpen, setIsOpen] = useState(false);
    const {
      closeMenu,
      highlightedIndex,
      setHighlightedIndex,
      getTriggerProps,
      getMenuProps,
      getItemProps,
      listRef,
      menuContainerRef,
      handleKeyDown
    } = useMenuInteraction({
      items,
      sectionsMeta,
      onItemActivate: handleItemActivate,
      selectedItemIds,
      displayAs,
      closeOnActivate: true,
      id,
      triggerRef,
      label,
      isOpen,
      setIsOpen,
      onImplicitClose,
      onExplicitClose
    });
    const debouncedOptionLoader = useDebouncedCallback((value) => {
      loadOptions(value, { initial: true });
    }, debounceMs);
    const handleInputChange = useCallback(
      (e) => {
        const value = e.target.value;
        setInputValue(value);
        debouncedOptionLoader(value);
        onSearchChange?.(value);
      },
      [debouncedOptionLoader, onSearchChange]
    );
    const handleInputKeyDown = useCallback(
      (e) => {
        onMenuKeyDown?.(e);
        handleKeyDown(e);
      },
      [handleKeyDown, onMenuKeyDown]
    );
    const getMenuPropsWithKeyDown = useCallback(
      (opts) => {
        const menuProps = getMenuProps(opts);
        if (!onMenuKeyDown) return menuProps;
        return {
          ...menuProps,
          onKeyDown: (e) => {
            onMenuKeyDown(e);
            menuProps.onKeyDown(e);
          }
        };
      },
      [getMenuProps, onMenuKeyDown]
    );
    useEffect(() => {
      const performInitialLoad = async () => {
        if (initialLoad === "immediate" && !initialLoadPerformed) {
          await loadOptions("", { initial: true });
          setInitialLoadPerformed(true);
        }
      };
      performInitialLoad();
    }, [
      loadOptions,
      initialLoadPerformed,
      initialLoad,
      setInitialLoadPerformed
    ]);
    const prevIsOpenRef = useRef(false);
    useEffect(() => {
      const wasOpen = prevIsOpenRef.current;
      prevIsOpenRef.current = isOpen;
      if (isOpen && !wasOpen) {
        if (initialLoad === "open" && !initialLoadPerformed) {
          loadOptions("", { initial: true }).then(() => {
            setInitialLoadPerformed(true);
          });
        }
        const selectedIdx = items.findIndex(
          (item) => item.original.id === selectedOption?.id
        );
        if (selectedIdx >= 0) {
          setHighlightedIndex(selectedIdx);
        }
      }
      if (!isOpen && wasOpen) {
        setInputValue("");
        loadOptions("", { initial: true });
      }
    }, [
      isOpen,
      initialLoad,
      initialLoadPerformed,
      loadOptions,
      setInitialLoadPerformed,
      items,
      selectedOption?.id,
      setHighlightedIndex
    ]);
    useEffect(() => {
      if (!isOpen || displayAs !== "popover") return;
      const frameId = requestAnimationFrame(() => {
        if (!disableSearch) {
          searchRef.current?.focus();
        } else {
          menuContainerRef.current?.focus();
        }
      });
      return () => cancelAnimationFrame(frameId);
    }, [isOpen, displayAs, disableSearch, menuContainerRef]);
    const handleLoadMore = async () => {
      await loadMore(searchValue);
    };
    const handleClickOutside = useCallback(() => {
      closeMenu({ restoreFocus: false });
    }, [closeMenu]);
    const triggerProps = getTriggerProps();
    const menuPropsForAria = getMenuProps();
    const activeDescendant = menuPropsForAria["aria-activedescendant"];
    const handleSearchClear = useCallback(() => {
      setInputValue("");
      debouncedOptionLoader("");
      onSearchChange?.("");
    }, [debouncedOptionLoader, onSearchChange]);
    const searchInput = !disableSearch ? /* @__PURE__ */ jsx(
      SearchField,
      {
        ref: searchRef,
        value: inputValue,
        onChange: handleInputChange,
        onKeyDown: handleInputKeyDown,
        onClear: handleSearchClear,
        "aria-activedescendant": activeDescendant,
        "aria-controls": menuPropsForAria.id,
        placeholder: searchPlaceholder,
        type: "search"
      }
    ) : null;
    const addNewItemButton = shouldShowAddNewItem(
      onAddNewItem,
      addItemLabel,
      inputValue
    ) ? /* @__PURE__ */ jsx(
      AddNewItemButton,
      {
        searchText: inputValue,
        addItemLabel,
        onAddNewItem,
        onCloseMenu: () => closeMenu({ restoreFocus: false })
      }
    ) : null;
    const wrappedClear = clear ? {
      ...clear,
      onClick: () => {
        clear.onClick();
        closeMenu();
      }
    } : void 0;
    const hasFooter = !!wrappedClear || !!addNewItemButton;
    const footer = hasFooter ? /* @__PURE__ */ jsx(MenuFooter, { clear: wrappedClear, addNew: addNewItemButton }) : void 0;
    if (displayAs === "dialog") {
      return /* @__PURE__ */ jsxs(Fragment, { children: [
        trigger(triggerProps),
        /* @__PURE__ */ jsx(
          OptionsDialog,
          {
            id: `${id}-dialog`,
            isOpen,
            onClose: closeMenu,
            title: label,
            field: searchInput ?? void 0,
            footer: footer ?? void 0,
            initialFocusResolver: !disableSearch ? (elements) => elements.find((el) => el.tagName === "INPUT") || elements[0] : void 0,
            children: /* @__PURE__ */ jsx(
              SelectOptions,
              {
                ref: listRef,
                isOpen: true,
                items,
                sectionsMeta,
                getMenuProps: (opts) => {
                  const menuProps = getMenuPropsWithKeyDown(opts);
                  if (disableSearch) {
                    return menuProps;
                  }
                  return { ...menuProps, tabIndex: -1 };
                },
                getItemProps,
                highlightedIndex,
                selectedOption,
                hasMore,
                onLoadMore: handleLoadMore,
                loading,
                loadingMore,
                virtualize
              }
            )
          }
        )
      ] });
    }
    return /* @__PURE__ */ jsxs(Fragment, { children: [
      trigger(triggerProps),
      /* @__PURE__ */ jsxs(
        OptionsPopover,
        {
          id: `${id}-popover`,
          referenceElement: triggerRef,
          open: isOpen && displayAs === "popover",
          onClose: handleClickOutside,
          width: popoverWidth ?? 320,
          footer: footer ?? void 0,
          children: [
            searchInput,
            /* @__PURE__ */ jsx(
              SelectOptions,
              {
                ref: listRef,
                isOpen,
                items,
                sectionsMeta,
                getMenuProps: (opts) => {
                  const menuProps = getMenuPropsWithKeyDown(opts);
                  if (disableSearch) {
                    return menuProps;
                  }
                  return { ...menuProps, tabIndex: -1 };
                },
                getItemProps,
                highlightedIndex,
                selectedOption,
                hasMore,
                onLoadMore: handleLoadMore,
                loading,
                loadingMore,
                virtualize
              }
            )
          ]
        }
      )
    ] });
  }
);
SelectMenu.displayName = "SelectMenu";

const SelectMenuSync = (props) => {
  const {
    options,
    filter: filterProp = defaultSyncFilter,
    groupSorter,
    ...rest
  } = props;
  const filter = useMemo(() => toSyncFilterFn(filterProp), [filterProp]);
  const loadOptions = (searchValue) => {
    const filtered = filter(options, searchValue);
    return groupSorter ? sortByGroup(filtered, groupSorter) : filtered;
  };
  const fieldRef = useRef(null);
  const prevOptionsRef = useRef(options);
  useEffect(() => {
    if (prevOptionsRef.current !== options) {
      prevOptionsRef.current = options;
      fieldRef.current?.invalidate();
    }
  }, [options]);
  return /* @__PURE__ */ jsx(
    SelectMenu,
    {
      ref: fieldRef,
      lazy: false,
      loadOptions,
      debounceMs: 0,
      ...rest
    }
  );
};

export { SelectMenu as S, SelectMenuSync as a };
//# sourceMappingURL=SelectMenuSync-BDx1yhZT.js.map
