import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
import { S as Spinner } from './Spinner-B7tTWcP6.js';
import { B as Button } from './Button-BNzCI47m.js';
import { c as cx } from './index-De1g9FRV.js';
import { useState, useRef, useCallback, useEffect, useMemo, forwardRef, useId, useImperativeHandle } from 'react';
import { u as useIntersectionObserver } from './useIntersectionObserver-BEmMDO3P.js';
import { T as Text } from './Text-mDcQHC2U.js';
import { D as Divider } from './Divider-C7fp5Xb6.js';
import { u as useMergeRefs } from './useMergeRefs-Dfmtq9cI.js';
import { S as SrOnly } from './SrOnly-pnf8ajnh.js';
import { I as Icon } from './Icon-B4uCvMU9.js';
import { S as SvgCheck } from './check-Cf67OWrZ.js';
import { b as OptionRow, c as OptionRowSideContent, d as OptionCheckbox, e as OptionContentArea, u as useAdaptiveView } from './useAdaptiveView-AvsDkChF.js';
import { d as defaultRangeExtractor, u as useVirtualizer } from './index-DXeGMe23.js';
import { S as SvgAdd } from './add-BcQkAUip.js';
import { m as matchSorter } from './match-sorter.esm-CGAauEiU.js';

import './syncFilterUtils.css';const DEFAULT_PAGE_SIZE = 20;
const DEFAULT_CACHE_MAX_SIZE = 15;
function useSelectFieldLoading(config) {
  const { lazy, loadOptions: loadOptionsProp, cache: cacheConfig } = config;
  const cacheEnabled = cacheConfig?.enabled !== false;
  const cacheMaxSize = cacheConfig?.maxSize ?? DEFAULT_CACHE_MAX_SIZE;
  const [options, setOptions] = useState([]);
  const [hasMoreToLoad, setHasMoreToLoad] = useState(false);
  const [previousGroup, setPreviousGroup] = useState(
    null
  );
  const [previousPage, setPreviousPage] = useState(0);
  const [previousOffset, setPreviousOffset] = useState(0);
  const [loading, setLoading] = useState(false);
  const [loadingMore, setLoadingMore] = useState(false);
  const [stateCache, setStateCache] = useState(
    () => /* @__PURE__ */ new Map()
  );
  const currentSearchValueRef = useRef("");
  const hasCompletedLoadRef = useRef(false);
  const appendOptions = useCallback((newOptions) => {
    setOptions((prevOptions) => prevOptions.concat(newOptions));
  }, []);
  const pageSize = lazy === "page" ? config.pageSize : DEFAULT_PAGE_SIZE;
  const limit = lazy === "offset" ? config.limit : DEFAULT_PAGE_SIZE;
  const restoreFromCache = useCallback((cached) => {
    setOptions(cached.options);
    setHasMoreToLoad(cached.hasMore);
    setPreviousPage(cached.previousPage);
    setPreviousOffset(cached.previousOffset);
    setPreviousGroup(cached.previousGroup);
  }, []);
  useEffect(() => {
    if (!cacheEnabled) return;
    const searchValue = currentSearchValueRef.current;
    if (!hasCompletedLoadRef.current) return;
    setStateCache((prev) => {
      if (prev.size >= cacheMaxSize) {
        prev.clear();
      }
      prev.set(searchValue, {
        options,
        hasMore: hasMoreToLoad,
        previousPage,
        previousOffset,
        previousGroup
      });
      return new Map(prev);
    });
  }, [
    cacheEnabled,
    cacheMaxSize,
    options,
    hasMoreToLoad,
    previousPage,
    previousOffset,
    previousGroup
  ]);
  const loadOptions = useCallback(
    async (searchValue, options2) => {
      const isInitial = !!options2?.initial;
      if (isInitial && cacheEnabled) {
        const cached = stateCache.get(searchValue);
        if (cached) {
          currentSearchValueRef.current = searchValue;
          restoreFromCache(cached);
          return;
        }
      }
      if (isInitial) {
        currentSearchValueRef.current = searchValue;
      }
      (isInitial ? setLoading : setLoadingMore)(true);
      try {
        if (!lazy) {
          const result = await loadOptionsProp(searchValue);
          const resolved = Array.isArray(result) ? result : await result;
          (isInitial ? setOptions : appendOptions)(resolved);
        } else {
          let result;
          if (lazy === "page") {
            const page = isInitial ? 0 : previousPage;
            result = await loadOptionsProp(searchValue, page, pageSize);
            setPreviousPage(isInitial ? 1 : page + 1);
          } else if (lazy === "offset") {
            const offset = isInitial ? 0 : previousOffset;
            result = await loadOptionsProp(searchValue, offset, limit);
            setPreviousOffset(isInitial ? limit : offset + limit);
          } else if (lazy === "group") {
            const group = isInitial ? null : previousGroup;
            result = await loadOptionsProp(searchValue, group);
            setPreviousGroup(
              result.options[result.options.length - 1]?.group ?? null
            );
          } else {
            throw new Error(
              `Invalid lazy mode: ${lazy}. Expected 'page', 'offset', or 'group'.`
            );
          }
          setHasMoreToLoad(result.hasMore ?? false);
          (isInitial ? setOptions : appendOptions)(result.options);
        }
        hasCompletedLoadRef.current = true;
      } finally {
        (isInitial ? setLoading : setLoadingMore)(false);
      }
    },
    [
      lazy,
      pageSize,
      limit,
      loadOptionsProp,
      appendOptions,
      previousPage,
      previousOffset,
      previousGroup,
      cacheEnabled,
      stateCache,
      restoreFromCache
    ]
  );
  const loadMore = useCallback(
    async (searchValue) => {
      await loadOptions(searchValue, { initial: false });
    },
    [loadOptions]
  );
  const reset = useCallback(() => {
    setOptions([]);
    setHasMoreToLoad(false);
    setPreviousGroup(null);
    setPreviousPage(0);
    setPreviousOffset(0);
    setLoading(false);
    setLoadingMore(false);
  }, []);
  const clearCache = useCallback(() => {
    setStateCache(/* @__PURE__ */ new Map());
  }, []);
  return {
    options,
    loading,
    loadingMore,
    hasMore: hasMoreToLoad,
    loadOptions,
    loadMore,
    reset,
    clearCache
  };
}

const empty = "_empty_1stqb_7";
const scroller = "_scroller_1stqb_23";
const divider = "_divider_1stqb_59";
const styles$1 = {
	"select-field-list": "_select-field-list_1stqb_2",
	empty: empty,
	"load-more": "_load-more_1stqb_15",
	scroller: scroller,
	"scroll-sentinel": "_scroll-sentinel_1stqb_34",
	"pinned-section": "_pinned-section_1stqb_42",
	"pinned-section-header": "_pinned-section-header_1stqb_46",
	"pinned-section-list": "_pinned-section-list_1stqb_53",
	divider: divider
};

const floating = "_floating_1d3fe_2";
const highlighted = "_highlighted_1d3fe_15";
const checkmark = "_checkmark_1d3fe_36";
const styles = {
	floating: floating,
	"bulk-action": "_bulk-action_1d3fe_9",
	highlighted: highlighted,
	"single-selected": "_single-selected_1d3fe_22",
	"single-selected-highlighted": "_single-selected-highlighted_1d3fe_29",
	checkmark: checkmark
};

const SelectOption = ({
  item,
  index,
  highlighted,
  disabled,
  getItemProps,
  selectionType,
  checked,
  isListScrolled = false
}) => {
  const isBulkAction = item.type === "select-all" || item.type === "select-filtered";
  const isSingleSelected = selectionType === "single" && checked === "checked";
  return /* @__PURE__ */ jsxs(
    OptionRow,
    {
      "data-item-index": index,
      disabled,
      ...getItemProps({
        item,
        index,
        "data-type": item.type,
        className: cx(styles["select-option"], {
          [styles.highlighted]: highlighted && !isSingleSelected,
          [styles["single-selected"]]: isSingleSelected && !highlighted,
          [styles["single-selected-highlighted"]]: isSingleSelected && highlighted,
          [styles["bulk-action"]]: isBulkAction,
          [styles.floating]: isBulkAction && isListScrolled
        })
      }),
      children: [
        selectionType === "multiple" && /* @__PURE__ */ jsx(OptionRowSideContent, { children: /* @__PURE__ */ jsx(OptionCheckbox, { checkState: checked }) }),
        /* @__PURE__ */ jsx(
          OptionContentArea,
          {
            label: item.original.label,
            content: item.original.content
          }
        ),
        selectionType === "single" && checked === "checked" && /* @__PURE__ */ jsx(OptionRowSideContent, { children: /* @__PURE__ */ jsx(
          Icon,
          {
            "aria-hidden": "true",
            size: "medium",
            svg: SvgCheck,
            className: styles["checkmark"]
          }
        ) })
      ]
    },
    item.id
  );
};

const InView = ({
  children,
  onVisibilityChange,
  rootMargin
}) => {
  const { ref } = useIntersectionObserver({
    onChange: (isIntersecting) => {
      onVisibilityChange?.(isIntersecting);
    },
    rootMargin
  });
  return /* @__PURE__ */ jsx("div", { ref, children });
};

const useOptionsSections = (items, sectionsMeta) => {
  return useMemo(() => {
    if (sectionsMeta.length === 0) {
      return [
        {
          type: "flat",
          items: items.map((item, index) => ({ item, index }))
        }
      ];
    }
    const result = [];
    const firstSectionStartIndex = Math.min(
      ...sectionsMeta.map((s) => s.startIndex)
    );
    if (firstSectionStartIndex > 0) {
      const flatItems = [];
      for (let i = 0; i < firstSectionStartIndex; i++) {
        if (items[i]) {
          flatItems.push({ item: items[i], index: i });
        }
      }
      if (flatItems.length > 0) {
        result.push({ type: "flat", items: flatItems });
      }
    }
    sectionsMeta.forEach((meta) => {
      const sectionItems = [];
      for (let i = meta.startIndex; i < meta.endIndex; i++) {
        if (items[i]) {
          sectionItems.push({ item: items[i], index: i });
        }
      }
      if (meta.type === "pinned") {
        if (sectionItems.length > 0 || meta.loading) {
          result.push({
            type: "pinned",
            label: meta.label,
            items: sectionItems,
            loading: meta.loading
          });
        }
      } else if (sectionItems.length > 0) {
        result.push({
          type: "group",
          label: meta.label,
          items: sectionItems
        });
      }
    });
    const lastSectionIndex = sectionsMeta.length > 0 ? Math.max(...sectionsMeta.map((s) => s.endIndex)) : 0;
    if (lastSectionIndex < items.length) {
      const flatItems = [];
      for (let i = lastSectionIndex; i < items.length; i++) {
        flatItems.push({ item: items[i], index: i });
      }
      if (flatItems.length > 0) {
        result.push({ type: "flat", items: flatItems });
      }
    }
    return result;
  }, [items, sectionsMeta]);
};
function flattenSectionsToVirtualRows(sections, hasMore) {
  const virtualRows = [];
  const downshiftIndexToVirtualRowIndex = {};
  const stickyIndices = [];
  sections.forEach((section, sectionIndex) => {
    const isLastSection = sectionIndex === sections.length - 1;
    if (section.type === "pinned" || section.type === "group") {
      virtualRows.push({
        type: "header",
        label: section.label,
        sectionIndex
      });
      section.items.forEach(({ item, index }) => {
        downshiftIndexToVirtualRowIndex[index] = virtualRows.length;
        virtualRows.push({ type: "item", item, index });
      });
      if (!isLastSection) {
        virtualRows.push({ type: "divider", sectionIndex });
      }
    } else {
      section.items.forEach(({ item, index }) => {
        const isBulkAction = item.type === "select-all" || item.type === "select-filtered";
        if (isBulkAction) {
          stickyIndices.push(virtualRows.length);
        }
        downshiftIndexToVirtualRowIndex[index] = virtualRows.length;
        virtualRows.push({ type: "item", item, index });
      });
    }
  });
  if (hasMore) {
    virtualRows.push({ type: "load-more" });
  }
  return { virtualRows, downshiftIndexToVirtualRowIndex, stickyIndices };
}

const OptionsPanel = forwardRef(
  ({
    isOpen,
    items,
    getMenuProps,
    getItemProps,
    highlightedIndex,
    getCheckedState,
    selectionType,
    hasMore,
    onLoadMore,
    loading,
    loadingMore,
    disableAutoLoadMore,
    disabled,
    className,
    style,
    sectionsMeta = []
  }, ref) => {
    const baseId = useId();
    const scrollSentinelRef = useRef(null);
    const scrollerRef = useRef(null);
    const [isScrolled, setIsScrolled] = useState(false);
    useImperativeHandle(ref, () => ({
      scrollToTop: () => {
        if (scrollerRef.current) {
          scrollerRef.current.scrollTop = 0;
        }
      },
      scrollToIndex: (index) => {
        if (!scrollerRef.current) return;
        if (index <= 0) {
          scrollerRef.current.scrollTop = 0;
          return;
        }
        const item = scrollerRef.current.querySelector(
          `[data-item-index="${index}"]`
        );
        if (item) {
          item.scrollIntoView({ block: "nearest" });
        }
      }
    }));
    useEffect(() => {
      if (!isOpen) {
        setIsScrolled(false);
        return;
      }
      if (!scrollSentinelRef.current) return;
      const observer = new IntersectionObserver(
        (entries) => {
          entries.forEach((entry) => {
            setIsScrolled(!entry.isIntersecting);
          });
        },
        { threshold: 0, root: scrollerRef.current }
      );
      observer.observe(scrollSentinelRef.current);
      return () => observer.disconnect();
    }, [isOpen]);
    const anyPinnedLoading = sectionsMeta.some(
      (s) => s.type === "pinned" && s.loading
    );
    const handleLoaderVisibilityChange = (visible) => {
      if (visible && !disableAutoLoadMore) {
        onLoadMore();
      }
    };
    const sections = useOptionsSections(items, sectionsMeta);
    const renderItem = (item, index) => /* @__PURE__ */ jsx(
      SelectOption,
      {
        item,
        index,
        getItemProps,
        selectionType,
        checked: getCheckedState(item),
        highlighted: highlightedIndex === index,
        disabled: (disabled || item.disabled) ?? false,
        isListScrolled: isScrolled
      },
      item.id
    );
    const renderSections = () => {
      const result = [];
      sections.forEach((section, sectionIndex) => {
        const isLastSection = sectionIndex === sections.length - 1;
        if (section.type === "pinned" || section.type === "group") {
          const labelId = `${baseId}-section-${sectionIndex}`;
          result.push(
            /* @__PURE__ */ jsxs(
              "div",
              {
                role: "group",
                "aria-labelledby": labelId,
                className: styles$1["pinned-section"],
                children: [
                  /* @__PURE__ */ jsx("span", { id: labelId, className: styles$1["pinned-section-header"], children: /* @__PURE__ */ jsx(Text, { variant: "eyebrow", children: section.label }) }),
                  /* @__PURE__ */ jsx("div", { className: styles$1["pinned-section-list"], children: section.items.map(
                    ({ item, index }) => renderItem(item, index)
                  ) })
                ]
              },
              `section-${sectionIndex}`
            )
          );
          if (!isLastSection) {
            result.push(
              // Decorative — group boundaries are already conveyed by role="group" with aria-labelledby
              /* @__PURE__ */ jsx(
                "div",
                {
                  role: "presentation",
                  "aria-hidden": "true",
                  className: styles$1["divider"],
                  children: /* @__PURE__ */ jsx(Divider, {})
                },
                `divider-${sectionIndex}`
              )
            );
          }
        } else {
          section.items.forEach(({ item, index }) => {
            result.push(renderItem(item, index));
          });
        }
      });
      return result;
    };
    const menuProps = getMenuProps({
      className: cx(styles$1["scroller"], className),
      style
    });
    const menuRef = useMergeRefs([menuProps.ref, scrollerRef]);
    return /* @__PURE__ */ jsx("div", { ...menuProps, ref: menuRef, children: /* @__PURE__ */ jsxs("div", { className: styles$1["select-field-list"], children: [
      isOpen && /* @__PURE__ */ jsx(
        "div",
        {
          ref: scrollSentinelRef,
          className: styles$1["scroll-sentinel"],
          role: "presentation",
          "aria-hidden": "true"
        }
      ),
      isOpen && /* @__PURE__ */ jsx(Fragment, { children: loading || anyPinnedLoading ? /* @__PURE__ */ jsx("div", { role: "presentation", className: styles$1["empty"], children: /* @__PURE__ */ jsx(Spinner, { size: "medium" }) }) : items.length > 0 ? renderSections() : /* @__PURE__ */ jsx("div", { role: "presentation", className: styles$1["empty"], children: /* @__PURE__ */ jsx(Text, { subdued: true, size: "small", children: "No match found" }) }) }),
      loadingMore ? /* @__PURE__ */ jsxs("div", { role: "presentation", className: styles$1["load-more"], children: [
        /* @__PURE__ */ jsx(Spinner, { size: "small" }),
        /* @__PURE__ */ jsx(SrOnly, { children: "Loading more..." })
      ] }) : hasMore && !loading ? /* @__PURE__ */ jsx("div", { role: "presentation", children: /* @__PURE__ */ jsx(
        InView,
        {
          onVisibilityChange: handleLoaderVisibilityChange,
          rootMargin: "0px 0px -100px 0px",
          children: /* @__PURE__ */ jsx("div", { className: styles$1["load-more"], children: /* @__PURE__ */ jsx(
            Button,
            {
              appearance: "secondary",
              size: "small",
              onClick: onLoadMore,
              children: "Load more"
            }
          ) })
        }
      ) }) : null
    ] }) });
  }
);
OptionsPanel.displayName = "OptionsPanel";

const EST_PADDING_BLOCK = 16;
const EST_LINE_HEIGHT = 18;
const EST_CHIP_ROW_HEIGHT = 28;
const EST_SIDE_CONTENT_HEIGHT = 40;
const EST_HEADER_HEIGHT = 32;
const EST_DIVIDER_HEIGHT = 17;
const EST_LOAD_MORE_HEIGHT = 40;
const EST_BASE_ITEM_HEIGHT = EST_PADDING_BLOCK + EST_LINE_HEIGHT;
function estimateRowHeight(row) {
  if (row.type === "header") return EST_HEADER_HEIGHT;
  if (row.type === "divider") return EST_DIVIDER_HEIGHT;
  if (row.type === "load-more") return EST_LOAD_MORE_HEIGHT;
  const content = row.item.original.content;
  if (!content) return EST_BASE_ITEM_HEIGHT;
  let contentHeight = EST_LINE_HEIGHT;
  if (content.description) contentHeight += EST_LINE_HEIGHT;
  if (content.chips?.length) contentHeight += EST_CHIP_ROW_HEIGHT;
  if (content.avatar || content.icon)
    contentHeight = Math.max(contentHeight, EST_SIDE_CONTENT_HEIGHT);
  return EST_PADDING_BLOCK + contentHeight;
}
const VirtualizedOptionsPanel = forwardRef(
  ({
    isOpen,
    items,
    getMenuProps,
    getItemProps,
    highlightedIndex,
    getCheckedState,
    selectionType,
    hasMore,
    onLoadMore,
    loading,
    loadingMore,
    disableAutoLoadMore,
    disabled,
    className,
    style,
    sectionsMeta = []
  }, ref) => {
    const baseId = useId();
    const scrollSentinelRef = useRef(null);
    const scrollerRef = useRef(null);
    const [isScrolled, setIsScrolled] = useState(false);
    useEffect(() => {
      if (!isOpen) {
        setIsScrolled(false);
        return;
      }
      if (!scrollSentinelRef.current) return;
      const observer = new IntersectionObserver(
        (entries) => {
          entries.forEach((entry) => {
            setIsScrolled(!entry.isIntersecting);
          });
        },
        { threshold: 0, root: scrollerRef.current }
      );
      observer.observe(scrollSentinelRef.current);
      return () => observer.disconnect();
    }, [isOpen]);
    const anyPinnedLoading = sectionsMeta.some(
      (s) => s.type === "pinned" && s.loading
    );
    const sections = useOptionsSections(items, sectionsMeta);
    const { virtualRows, downshiftIndexToVirtualRowIndex, stickyIndices } = useMemo(
      () => flattenSectionsToVirtualRows(sections, hasMore),
      [sections, hasMore]
    );
    const stickyHeightRef = useRef(EST_BASE_ITEM_HEIGHT);
    const rangeExtractor = useCallback(
      (range) => {
        if (stickyIndices.length === 0) {
          return defaultRangeExtractor(range);
        }
        const activeStickyIndex = [...stickyIndices].reverse().find((index) => range.startIndex >= index) ?? 0;
        const next = /* @__PURE__ */ new Set([
          activeStickyIndex,
          ...defaultRangeExtractor(range)
        ]);
        return [...next].sort((a, b) => a - b);
      },
      [stickyIndices]
    );
    const virtualizer = useVirtualizer({
      count: virtualRows.length,
      getScrollElement: () => scrollerRef.current,
      estimateSize: (index) => estimateRowHeight(virtualRows[index]),
      overscan: 5,
      rangeExtractor,
      scrollPaddingStart: stickyIndices.length > 0 ? stickyHeightRef.current : 0,
      enabled: isOpen,
      getItemKey: (index) => {
        const row = virtualRows[index];
        if (row.type === "item") return row.item.id;
        if (row.type === "header") return `header-${row.sectionIndex}`;
        if (row.type === "divider") return `divider-${row.sectionIndex}`;
        return "load-more";
      }
    });
    const virtualItems = virtualizer.getVirtualItems();
    if (stickyIndices.length > 0) {
      const stickyItem = virtualItems.find(
        (vi) => stickyIndices.includes(vi.index)
      );
      if (stickyItem) {
        stickyHeightRef.current = stickyItem.size;
      }
    }
    const downshiftMapRef = useRef(downshiftIndexToVirtualRowIndex);
    downshiftMapRef.current = downshiftIndexToVirtualRowIndex;
    const virtualizerRef = useRef(virtualizer);
    virtualizerRef.current = virtualizer;
    useImperativeHandle(ref, () => ({
      scrollToTop: () => {
        if (virtualizerRef.current) {
          virtualizerRef.current.scrollToOffset(0);
        }
      },
      scrollToIndex: (index) => {
        if (index <= 0) {
          virtualizerRef.current.scrollToOffset(0);
          return;
        }
        const virtualRowIndex = downshiftMapRef.current[index];
        if (virtualRowIndex != null) {
          virtualizerRef.current.scrollToIndex(virtualRowIndex, {
            align: "auto"
          });
        }
      }
    }));
    const onLoadMoreRef = useRef(onLoadMore);
    onLoadMoreRef.current = onLoadMore;
    useEffect(() => {
      if (!hasMore || loadingMore || disableAutoLoadMore) return;
      const lastItem = virtualItems[virtualItems.length - 1];
      if (!lastItem) return;
      if (lastItem.index >= virtualRows.length - 1) {
        onLoadMoreRef.current();
      }
    }, [
      hasMore,
      loadingMore,
      disableAutoLoadMore,
      virtualItems,
      virtualRows.length
    ]);
    const isSticky = useCallback(
      (index) => stickyIndices.includes(index),
      [stickyIndices]
    );
    const renderVirtualRow = (row) => {
      if (row.type === "item") {
        return /* @__PURE__ */ jsx(
          SelectOption,
          {
            item: row.item,
            index: row.index,
            getItemProps,
            selectionType,
            checked: getCheckedState(row.item),
            highlighted: highlightedIndex === row.index,
            disabled: (disabled || row.item.disabled) ?? false,
            isListScrolled: isScrolled
          }
        );
      }
      if (row.type === "header") {
        const labelId = `${baseId}-section-${row.sectionIndex}`;
        return /* @__PURE__ */ jsx(
          "div",
          {
            role: "presentation",
            "aria-hidden": "true",
            className: styles$1["pinned-section-header"],
            children: /* @__PURE__ */ jsx("span", { id: labelId, children: /* @__PURE__ */ jsx(Text, { variant: "eyebrow", children: row.label }) })
          }
        );
      }
      if (row.type === "divider") {
        return (
          // Decorative — group boundaries are already conveyed by role="group" with aria-labelledby
          /* @__PURE__ */ jsx(
            "div",
            {
              role: "presentation",
              "aria-hidden": "true",
              className: styles$1["divider"],
              children: /* @__PURE__ */ jsx(Divider, {})
            }
          )
        );
      }
      if (row.type === "load-more") {
        if (loadingMore) {
          return /* @__PURE__ */ jsxs("div", { role: "presentation", className: styles$1["load-more"], children: [
            /* @__PURE__ */ jsx(Spinner, { size: "small" }),
            /* @__PURE__ */ jsx(SrOnly, { children: "Loading more..." })
          ] });
        }
        return /* @__PURE__ */ jsx("div", { role: "presentation", children: /* @__PURE__ */ jsx("div", { className: styles$1["load-more"], children: /* @__PURE__ */ jsx(
          Button,
          {
            appearance: "secondary",
            size: "small",
            onClick: () => onLoadMoreRef.current(),
            children: "Load more"
          }
        ) }) });
      }
      return null;
    };
    const menuProps = getMenuProps({
      className: cx(styles$1["scroller"], className),
      style
    });
    const menuRef = useMergeRefs([menuProps.ref, scrollerRef]);
    return /* @__PURE__ */ jsx("div", { ...menuProps, ref: menuRef, children: /* @__PURE__ */ jsxs("div", { className: styles$1["select-field-list"], children: [
      isOpen && /* @__PURE__ */ jsx(
        "div",
        {
          ref: scrollSentinelRef,
          className: styles$1["scroll-sentinel"],
          role: "presentation",
          "aria-hidden": "true"
        }
      ),
      isOpen && /* @__PURE__ */ jsx(Fragment, { children: loading || anyPinnedLoading ? /* @__PURE__ */ jsx("div", { role: "presentation", className: styles$1["empty"], children: /* @__PURE__ */ jsx(Spinner, { size: "medium" }) }) : items.length > 0 ? /* @__PURE__ */ jsx(
        "div",
        {
          role: "presentation",
          "aria-hidden": "true",
          style: {
            height: virtualizer.getTotalSize(),
            width: "100%",
            position: "relative"
          },
          children: virtualItems.map((virtualItem) => {
            const row = virtualRows[virtualItem.index];
            const sticky = isSticky(virtualItem.index);
            return /* @__PURE__ */ jsx(
              "div",
              {
                "data-index": virtualItem.index,
                ref: virtualizer.measureElement,
                style: sticky ? {
                  position: "sticky",
                  top: 0,
                  zIndex: 1
                } : {
                  position: "absolute",
                  top: 0,
                  left: 0,
                  width: "100%",
                  transform: `translateY(${virtualItem.start}px)`
                },
                children: renderVirtualRow(row)
              },
              virtualItem.key
            );
          })
        }
      ) : /* @__PURE__ */ jsx("div", { role: "presentation", className: styles$1["empty"], children: /* @__PURE__ */ jsx(Text, { subdued: true, size: "small", children: "No match found" }) }) })
    ] }) });
  }
);
VirtualizedOptionsPanel.displayName = "VirtualizedOptionsPanel";

const DEFAULT_CACHE_SIZE = 15;
const STATIC_CACHE_KEY = "__static__";
function cacheSet(sectionCache, key, value, maxSize) {
  if (sectionCache.has(key)) {
    sectionCache.delete(key);
  }
  sectionCache.set(key, value);
  while (sectionCache.size > maxSize) {
    const oldest = sectionCache.keys().next().value;
    if (oldest !== void 0) {
      sectionCache.delete(oldest);
    }
  }
}
function usePinnedOptions(pinned, searchValue) {
  const [dynamicResults, setDynamicResults] = useState({});
  const [loadingSet, setLoadingSet] = useState(/* @__PURE__ */ new Set());
  const latestSearchValueRef = useRef(searchValue);
  latestSearchValueRef.current = searchValue;
  const cacheRef = useRef(
    /* @__PURE__ */ new Map()
  );
  const nonReactiveTriggeredRef = useRef(/* @__PURE__ */ new Set());
  const sections = useMemo(() => {
    if (!pinned) return [];
    return Array.isArray(pinned) ? pinned : [pinned];
  }, [pinned]);
  const sectionConfig = useMemo(() => {
    return sections.map((section) => {
      const isDynamic = typeof section.options === "function";
      return {
        label: section.label,
        isDynamic,
        searchReactive: section.searchReactive ?? true,
        cacheSize: section.cacheSize ?? DEFAULT_CACHE_SIZE,
        staticOptions: isDynamic ? void 0 : section.options,
        loader: isDynamic ? section.options : void 0
      };
    });
  }, [sections]);
  useEffect(() => {
    cacheRef.current = /* @__PURE__ */ new Map();
    nonReactiveTriggeredRef.current = /* @__PURE__ */ new Set();
  }, [sectionConfig]);
  const getSectionCache = useCallback(
    (index) => {
      let sectionCache = cacheRef.current.get(index);
      if (!sectionCache) {
        sectionCache = /* @__PURE__ */ new Map();
        cacheRef.current.set(index, sectionCache);
      }
      return sectionCache;
    },
    []
  );
  const loadSection = useCallback(
    (config, index, loaderArg) => {
      const cacheKey = config.searchReactive ? loaderArg : STATIC_CACHE_KEY;
      const handleResult = (options) => {
        if (!config.searchReactive || latestSearchValueRef.current === loaderArg) {
          const sectionCache = getSectionCache(index);
          cacheSet(sectionCache, cacheKey, options, config.cacheSize);
          setDynamicResults((prev) => ({ ...prev, [index]: options }));
          setLoadingSet((prev) => {
            const next = new Set(prev);
            next.delete(index);
            return next;
          });
        }
      };
      const handleError = (error) => {
        console.error("Failed to load pinned options:", error);
        if (!config.searchReactive || latestSearchValueRef.current === loaderArg) {
          setDynamicResults((prev) => ({ ...prev, [index]: [] }));
          setLoadingSet((prev) => {
            const next = new Set(prev);
            next.delete(index);
            return next;
          });
        }
      };
      try {
        Promise.resolve(config.loader(loaderArg)).then(handleResult).catch(handleError);
      } catch (error) {
        handleError(error);
      }
    },
    [getSectionCache]
  );
  useEffect(() => {
    const dynamicEntries = sectionConfig.map((config, index) => ({ config, index })).filter(({ config }) => config.isDynamic);
    if (dynamicEntries.length === 0) return;
    const toLoad = [];
    const preResolved = {};
    dynamicEntries.forEach(({ config, index }) => {
      const sectionCache = getSectionCache(index);
      if (config.searchReactive) {
        const cached = sectionCache.get(searchValue);
        if (cached) {
          preResolved[index] = cached;
        } else {
          toLoad.push({ config, index });
        }
      } else {
        const cached = sectionCache.get(STATIC_CACHE_KEY);
        if (cached) {
          preResolved[index] = cached;
        } else if (!nonReactiveTriggeredRef.current.has(index)) {
          nonReactiveTriggeredRef.current.add(index);
          toLoad.push({ config, index });
        }
      }
    });
    if (toLoad.length === 0) {
      setDynamicResults(preResolved);
      setLoadingSet(/* @__PURE__ */ new Set());
      return;
    }
    const loadingIndices = toLoad.map(({ index }) => index);
    setDynamicResults(preResolved);
    setLoadingSet(new Set(loadingIndices));
    toLoad.forEach(({ config, index }) => {
      const loaderArg = config.searchReactive ? searchValue : "";
      loadSection(config, index, loaderArg);
    });
  }, [sectionConfig, searchValue, loadSection, getSectionCache]);
  const pinnedSections = useMemo(() => {
    return sectionConfig.map((config, index) => {
      if (!config.isDynamic) {
        return { label: config.label, options: config.staticOptions };
      }
      if (!loadingSet.has(index) && index in dynamicResults) {
        return {
          label: config.label,
          options: dynamicResults[index]
        };
      }
      return { label: config.label, options: [], loading: true };
    });
  }, [sectionConfig, dynamicResults, loadingSet]);
  return { pinnedSections };
}

function useGroupedOptions(options, groupToString) {
  return useMemo(() => {
    const groupedItems = [];
    const ungroupedItems = [];
    const groupSections = [];
    const groupMap = /* @__PURE__ */ new Map();
    options.forEach((option) => {
      if (option.group !== void 0) {
        const groupValue = option.group;
        if (!groupMap.has(groupValue)) {
          const label = groupToString ? groupToString(groupValue) : String(groupValue);
          groupMap.set(groupValue, { label, options: [] });
        }
        groupMap.get(groupValue).options.push(option);
        groupedItems.push({
          id: option.id,
          type: "grouped-option",
          original: option,
          disabled: option.disabled ?? false
        });
      } else {
        ungroupedItems.push({
          id: option.id,
          type: "option",
          original: option,
          disabled: option.disabled ?? false
        });
      }
    });
    groupMap.forEach(({ label, options: groupOptions }) => {
      groupSections.push({ label, options: groupOptions });
    });
    return { groupedItems, ungroupedItems, groupSections };
  }, [options, groupToString]);
}
function sortGroupSections(sections, groupSorter) {
  return [...sections].sort((a, b) => {
    const groupA = a.options[0]?.group;
    const groupB = b.options[0]?.group;
    if (groupA === void 0 || groupB === void 0) return 0;
    return groupSorter(groupA, groupB);
  });
}

const useProcessedOptions = ({
  options,
  pinned,
  searchValue,
  groupToString,
  groupSorter
}) => {
  const { pinnedSections } = usePinnedOptions(pinned, searchValue);
  const { ungroupedItems, groupSections: rawGroupSections } = useGroupedOptions(
    options,
    groupToString
  );
  const groupSections = useMemo(() => {
    if (groupSorter && rawGroupSections.length > 0) {
      return sortGroupSections(rawGroupSections, groupSorter);
    }
    return rawGroupSections;
  }, [rawGroupSections, groupSorter]);
  return { pinnedSections, ungroupedItems, groupSections };
};

function toSelectItem(option) {
  return {
    id: option.id,
    type: "option",
    disabled: option.disabled ?? false,
    original: option
  };
}
function buildSelectItems({
  prefixItems,
  pinnedSections,
  groupSections,
  ungroupedItems
}) {
  const items = [];
  const meta = [];
  if (prefixItems) {
    items.push(...prefixItems);
  }
  pinnedSections.forEach((section) => {
    const startIndex = items.length;
    section.options.forEach((option) => {
      items.push({
        id: option.id + "-pinned",
        type: "pinned-option",
        original: option,
        disabled: option.disabled ?? false
      });
    });
    const endIndex = items.length;
    if (endIndex > startIndex || section.loading) {
      meta.push({
        type: "pinned",
        label: section.label,
        startIndex,
        endIndex,
        loading: section.loading
      });
    }
  });
  groupSections.forEach((section) => {
    const startIndex = items.length;
    section.options.forEach((option) => {
      items.push({
        id: option.id,
        type: "grouped-option",
        original: option,
        disabled: option.disabled ?? false
      });
    });
    const endIndex = items.length;
    if (endIndex > startIndex) {
      meta.push({
        type: "group",
        label: section.label,
        startIndex,
        endIndex
      });
    }
  });
  items.push(...ungroupedItems);
  return { items, sectionsMeta: meta };
}

function resolveAddItemLabel(addItemLabel, searchText) {
  if (typeof addItemLabel === "function") {
    return addItemLabel(searchText) ?? null;
  }
  return addItemLabel ?? "Add new item";
}
function shouldShowAddNewItem(onAddNewItem, addItemLabel, searchText) {
  return onAddNewItem != null && resolveAddItemLabel(addItemLabel, searchText) != null;
}

const AddNewItemButton = ({
  searchText,
  addItemLabel,
  onAddNewItem,
  onCloseMenu
}) => {
  if (!onAddNewItem) return null;
  const resolvedLabel = resolveAddItemLabel(addItemLabel, searchText);
  if (resolvedLabel == null) return null;
  return /* @__PURE__ */ jsx(
    Button,
    {
      appearance: "secondary",
      size: "small",
      icon: { before: SvgAdd },
      onMouseDown: (e) => e.preventDefault(),
      onClick: () => {
        onCloseMenu?.();
        onAddNewItem(searchText);
      },
      style: { width: "100%" },
      children: resolvedLabel
    }
  );
};
AddNewItemButton.displayName = "AddNewItemButton";

function useSelectOrchestration(config) {
  const {
    lazy,
    loadOptions: loadOptionsProp,
    cache,
    lazyOptions,
    initialLoad: initialLoadProp = "auto",
    displayMenuAs: displayMenuAsProp = "auto",
    ref
  } = config;
  const [initialLoadPerformed, setInitialLoadPerformed] = useState(false);
  const { isMobile } = useAdaptiveView();
  const displayAs = displayMenuAsProp === "auto" ? isMobile ? "dialog" : "popover" : displayMenuAsProp;
  const initialLoad = initialLoadProp === "auto" ? "immediate" : initialLoadProp;
  const pageSize = lazy === "page" ? lazyOptions?.pageSize ?? DEFAULT_PAGE_SIZE : DEFAULT_PAGE_SIZE;
  const limit = lazy === "offset" ? lazyOptions?.limit ?? DEFAULT_PAGE_SIZE : DEFAULT_PAGE_SIZE;
  const loadingHookConfig = useMemo(() => {
    const cacheConfig = {
      enabled: cache?.enabled,
      maxSize: cache?.maxSize
    };
    if (lazy === "page")
      return {
        lazy: "page",
        loadOptions: loadOptionsProp,
        pageSize,
        cache: cacheConfig
      };
    if (lazy === "offset")
      return {
        lazy: "offset",
        loadOptions: loadOptionsProp,
        limit,
        cache: cacheConfig
      };
    if (lazy === "group")
      return {
        lazy: "group",
        loadOptions: loadOptionsProp,
        cache: cacheConfig
      };
    return {
      lazy: false,
      loadOptions: loadOptionsProp,
      cache: cacheConfig
    };
  }, [lazy, loadOptionsProp, pageSize, limit, cache?.enabled, cache?.maxSize]);
  const {
    options,
    loading,
    loadingMore,
    hasMore,
    loadOptions,
    loadMore,
    clearCache
  } = useSelectFieldLoading(loadingHookConfig);
  useImperativeHandle(
    ref,
    () => ({
      clearCache,
      invalidate: () => {
        clearCache();
        setInitialLoadPerformed(false);
      }
    }),
    [clearCache]
  );
  return {
    displayAs,
    initialLoad,
    initialLoadPerformed,
    setInitialLoadPerformed,
    options,
    loading,
    loadingMore,
    hasMore,
    loadOptions,
    loadMore
  };
}

const defaultSyncFilter = (options, searchValue) => matchSorter(options, searchValue, {
  keys: ["label", "searchText"],
  baseSort: (a, b) => a.index - b.index
});
const toSyncFilterFn = (filter) => typeof filter === "function" ? filter : (options, searchValue) => matchSorter(options, searchValue, {
  baseSort: (a, b) => a.index - b.index,
  ...filter
});
const sortByGroup = (options, groupSorter) => {
  const groupOrder = /* @__PURE__ */ new Map();
  const uniqueGroups = [];
  options.forEach((opt) => {
    if (!groupOrder.has(opt.group)) {
      groupOrder.set(opt.group, uniqueGroups.length);
      uniqueGroups.push(opt.group);
    }
  });
  uniqueGroups.sort((a, b) => {
    if (a === void 0 && b === void 0) return 0;
    if (a === void 0) return 1;
    if (b === void 0) return -1;
    return groupSorter(a, b);
  });
  uniqueGroups.forEach((group, index) => {
    groupOrder.set(group, index);
  });
  return [...options].sort((a, b) => {
    const orderA = groupOrder.get(a.group) ?? Infinity;
    const orderB = groupOrder.get(b.group) ?? Infinity;
    return orderA - orderB;
  });
};

export { AddNewItemButton as A, OptionsPanel as O, VirtualizedOptionsPanel as V, useProcessedOptions as a, buildSelectItems as b, sortByGroup as c, defaultSyncFilter as d, toSelectItem as e, shouldShowAddNewItem as s, toSyncFilterFn as t, useSelectOrchestration as u };
//# sourceMappingURL=syncFilterUtils-BVclVovw.js.map
