import { jsxs, jsx, Fragment } from "react/jsx-runtime";
import * as React from "react";
import { Search, Plus } from "lucide-react";
import { cn } from "../../lib/utils.js";
import { Popover, PopoverTrigger, PopoverContent } from "../Popover/popover.js";
import { Command, CommandList, CommandEmpty, CommandSeparator, CommandGroup, CommandItem } from "../Command/command.js";
import { Command as Command$1 } from "cmdk";
import { MenuItem, MenuFooter } from "../Menu/menu-item.js";
import { Empty } from "../Empty/empty.js";
import { CircularProgress } from "../CircularProgress/circular-progress.js";
import { OVERLAY_SIDE_OFFSET } from "../../tokens/elevation/overlay-geometry.js";
import { getMenuListMinHeight } from "../Field/field-types.js";
import { RowSizeProvider, ICON_SIZE } from "../../patterns/element-anatomy/item-anatomy.js";
import { clearSelection, applySelectAll } from "../../lib/multi-select-ordering.js";
const SelectMenu = React.forwardRef(function SelectMenu2({
  options,
  groups,
  value,
  onValueChange,
  multiple = false,
  searchable = false,
  creatable = false,
  onCreate,
  createLabel = (q) => `直接使用「${q}」`,
  children,
  searchPlaceholder = "搜尋…",
  // i18n-allow: DS default; consumer override via searchPlaceholder prop
  emptyText = "沒有符合的選項",
  // i18n-allow: DS default; consumer override via emptyText prop
  loading = false,
  size = "md",
  align = "start",
  minRows = 3,
  minWidth,
  open: controlledOpen,
  defaultOpen,
  onOpenChange: controlledOnOpenChange,
  renderLabel,
  onOpenAutoFocus,
  contentId,
  className
}, _ref) {
  const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false);
  const open = controlledOpen ?? internalOpen;
  const setOpen = controlledOnOpenChange ?? setInternalOpen;
  const [search, setSearch] = React.useState("");
  const selectedValues = React.useMemo(() => {
    if (value == null) return [];
    return Array.isArray(value) ? value : [value];
  }, [value]);
  const isSelected = React.useCallback(
    (v) => selectedValues.includes(v),
    [selectedValues]
  );
  const handleSelect = React.useCallback(
    (optionValue) => {
      if (multiple) {
        const next = isSelected(optionValue) ? selectedValues.filter((v) => v !== optionValue) : [...selectedValues, optionValue];
        onValueChange == null ? void 0 : onValueChange(next);
      } else {
        onValueChange == null ? void 0 : onValueChange(optionValue);
        setOpen(false);
      }
    },
    [multiple, selectedValues, isSelected, onValueChange, setOpen]
  );
  const selectableOptions = React.useMemo(
    () => options.filter((o) => !o.disabled),
    [options]
  );
  const allState = React.useMemo(() => {
    if (!multiple) return false;
    const count = selectableOptions.filter((o) => isSelected(o.value)).length;
    if (count === 0) return false;
    if (count === selectableOptions.length) return true;
    return "indeterminate";
  }, [multiple, selectableOptions, isSelected]);
  const handleSelectAll = React.useCallback(() => {
    if (!multiple) return;
    if (allState === true) {
      onValueChange == null ? void 0 : onValueChange(clearSelection());
    } else {
      onValueChange == null ? void 0 : onValueChange(applySelectAll(selectedValues, selectableOptions.map((o) => o.value)));
    }
  }, [multiple, allState, selectableOptions, selectedValues, onValueChange]);
  const showCreate = React.useMemo(() => {
    if (!creatable || !search.trim()) return false;
    return !options.some(
      (o) => o.label.toLowerCase() === search.trim().toLowerCase()
    );
  }, [creatable, search, options]);
  const groupedOptions = React.useMemo(() => {
    if (!(groups == null ? void 0 : groups.length)) return [{ key: "__default", label: "", options }];
    const grouped = groups.map((g) => ({
      ...g,
      options: options.filter((o) => o.group === g.key)
    }));
    const ungrouped = options.filter((o) => !o.group);
    if (ungrouped.length) {
      grouped.unshift({ key: "__default", label: "", options: ungrouped });
    }
    return grouped;
  }, [groups, options]);
  React.useEffect(() => {
    if (!open) setSearch("");
  }, [open]);
  const handleNonSearchableAutoFocus = React.useCallback((e) => {
    e.preventDefault();
    const root = e.currentTarget.querySelector("[cmdk-root]");
    root == null ? void 0 : root.focus({ preventScroll: true });
  }, []);
  return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
    /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children }),
    /* @__PURE__ */ jsx(RowSizeProvider, { value: size, children: /* @__PURE__ */ jsx(
      PopoverContent,
      {
        id: contentId,
        className: cn(
          "p-0 w-auto rounded-lg border border-border bg-surface-raised overflow-hidden",
          className
        ),
        style: {
          boxShadow: "var(--elevation-200)",
          minWidth: minWidth ?? "max(var(--radix-popover-trigger-width), 15rem)"
        },
        align,
        sideOffset: OVERLAY_SIDE_OFFSET,
        onOpenAutoFocus: onOpenAutoFocus ?? (!searchable ? handleNonSearchableAutoFocus : void 0),
        onInteractOutside: (e) => {
          const target = e.detail.originalEvent.target;
          if (target == null ? void 0 : target.closest("[data-radix-popper-content-wrapper]")) {
            e.preventDefault();
          }
        },
        children: /* @__PURE__ */ jsxs(Command, { shouldFilter: searchable, className: "bg-transparent", children: [
          searchable && /* @__PURE__ */ jsxs("div", { className: cn(
            "flex items-center gap-2 px-3 py-1 border-b border-divider",
            size === "lg" ? "min-h-[calc(var(--field-height-lg)+8px)]" : size === "sm" ? "min-h-[calc(var(--field-height-sm)+8px)]" : "min-h-[calc(var(--field-height-md)+8px)]"
          ), children: [
            /* @__PURE__ */ jsx(Search, { size: ICON_SIZE[size], className: "shrink-0 text-fg-muted", "aria-hidden": true }),
            /* @__PURE__ */ jsx(
              Command$1.Input,
              {
                placeholder: searchPlaceholder,
                value: search,
                onValueChange: setSearch,
                className: cn(
                  "flex w-full bg-transparent outline-none placeholder:text-fg-muted",
                  // M24 disabled state precedence:disabled 時 placeholder 切 fg-disabled(audit dim 34)
                  "disabled:placeholder:text-fg-disabled disabled:text-fg-disabled disabled:cursor-not-allowed",
                  size === "lg" ? "text-body-lg leading-compact" : "text-body leading-compact"
                )
              }
            )
          ] }),
          /* @__PURE__ */ jsxs(CommandList, { className: "relative", children: [
            /* @__PURE__ */ jsx(
              CommandEmpty,
              {
                className: "flex items-center justify-center",
                style: { minHeight: getMenuListMinHeight(size, minRows) },
                children: loading ? /* @__PURE__ */ jsx(Empty, { icon: /* @__PURE__ */ jsx(CircularProgress, { size: 48 }), className: "py-6" }) : /* @__PURE__ */ jsx(Empty, { description: emptyText, className: "py-6" })
              }
            ),
            groupedOptions.map((group, gi) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
              gi > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
              /* @__PURE__ */ jsxs(CommandGroup, { className: "p-0 py-2", children: [
                group.label && /* @__PURE__ */ jsx(MenuItem, { size, header: true, children: group.label }),
                group.options.map((opt) => /* @__PURE__ */ jsx(
                  CommandItem,
                  {
                    value: opt.label,
                    keywords: opt.description ? [opt.description] : void 0,
                    disabled: opt.disabled,
                    onSelect: () => handleSelect(opt.value),
                    className: "p-0 rounded-none data-[selected=true]:bg-transparent",
                    children: /* @__PURE__ */ jsx(
                      MenuItem,
                      {
                        size,
                        startIcon: opt.icon,
                        avatar: opt.avatar,
                        description: opt.description,
                        checkbox: multiple,
                        checked: isSelected(opt.value),
                        selected: !multiple && isSelected(opt.value),
                        disabled: opt.disabled,
                        children: renderLabel ? renderLabel(opt) : opt.label
                      }
                    )
                  },
                  opt.value
                ))
              ] })
            ] }, group.key)),
            showCreate && /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsx(CommandSeparator, {}),
              /* @__PURE__ */ jsx(CommandGroup, { className: "p-0 py-2", children: /* @__PURE__ */ jsx(
                CommandItem,
                {
                  value: search,
                  onSelect: () => {
                    onCreate == null ? void 0 : onCreate(search.trim());
                    setSearch("");
                  },
                  className: "p-0 rounded-none data-[selected=true]:bg-transparent",
                  children: /* @__PURE__ */ jsx(MenuItem, { size, startIcon: Plus, children: createLabel(search.trim()) })
                }
              ) })
            ] })
          ] }),
          multiple && selectableOptions.length > 0 && !search && /* @__PURE__ */ jsx(MenuFooter, { children: /* @__PURE__ */ jsx(
            MenuItem,
            {
              size,
              checkbox: true,
              checked: allState,
              onClick: handleSelectAll,
              children: "全部"
            }
          ) })
        ] })
      }
    ) })
  ] });
});
SelectMenu.displayName = "SelectMenu";
const selectMenuMeta = {
  component: "SelectMenu",
  family: 4,
  variants: {},
  sizes: {},
  states: ["default", "hover", "active", "focus-visible", "disabled"],
  tokens: {
    bg: ["bg-surface-raised", "bg-transparent"],
    fg: ["text-fg-muted"],
    ring: []
  }
};
export {
  SelectMenu,
  selectMenuMeta
};
//# sourceMappingURL=select-menu.js.map
