'use strict';

var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var utils = require('./utils-CTr7wn5d.js');
var primitives_Popover = require('./primitives/Popover.js');
var SelectFieldWrapper = require('./SelectFieldWrapper-DEA--2wj.js');
var Tree = require('./Tree-BPd0DuLh.js');
var x = require('./x-Brw3FJst.js');
var chevronDown = require('./chevron-down-CPsWSS51.js');

const pruneTree = (nodes, searchTerm) => {
    if (!searchTerm.trim())
        return nodes;
    const lower = searchTerm.toLowerCase();
    const prune = (items) => items.reduce((acc, node) => {
        const titleStr = typeof node.title === "string" ? node.title : "";
        const nodeMatches = titleStr.toLowerCase().includes(lower);
        if (nodeMatches) {
            acc.push(node);
        }
        else {
            const prunedChildren = node.children ? prune(node.children) : [];
            if (prunedChildren.length > 0) {
                acc.push({ ...node, children: prunedChildren });
            }
        }
        return acc;
    }, []);
    return prune(nodes);
};

const resolveFieldNames = (nodes, fieldNames) => {
    const labelKey = fieldNames.label ?? "title";
    const valueKey = fieldNames.value ?? "key";
    const remap = (items) => items.map(item => ({
        key: String(item[valueKey] ?? ""),
        title: item[labelKey],
        disabled: item.disabled,
        children: Array.isArray(item.children)
            ? remap(item.children)
            : undefined,
    }));
    return remap(nodes);
};

function useTreeSelectValue(props) {
    const { value: valueProp, defaultValue, onChange, treeData: rawTreeData, fieldNames, isClearable = false, isDisabled = false, size = "medium", label = "", error = "", helpText = "", required = false, } = props;
    const id = React.useId();
    const errorId = `error_${id}`;
    const helpTextId = `helpText_${id}`;
    const treeData = React.useMemo(() => {
        if (!fieldNames)
            return rawTreeData;
        return resolveFieldNames(rawTreeData, fieldNames);
    }, [rawTreeData, fieldNames?.label, fieldNames?.value]);
    const isControlled = valueProp !== undefined;
    const [internalValue, setInternalValue] = React.useState(defaultValue ?? "");
    const currentValue = isControlled ? (valueProp ?? "") : internalValue;
    const applyValue = React.useCallback((next) => {
        if (!isControlled)
            setInternalValue(next);
        onChange?.(next);
    }, [isControlled, onChange]);
    const selectedLabel = React.useMemo(() => {
        if (!currentValue)
            return "";
        const node = Tree.findNode(currentValue, treeData);
        if (!node)
            return currentValue;
        return typeof node.title === "string" ? node.title : "";
    }, [currentValue, treeData]);
    const handleClear = React.useCallback((e) => {
        e.stopPropagation();
        applyValue("");
    }, [applyValue]);
    const showClearButton = isClearable && !!currentValue && !isDisabled;
    return {
        id,
        errorId,
        helpTextId,
        label,
        error,
        helpText,
        required,
        isDisabled,
        size,
        treeData,
        currentValue,
        selectedLabel,
        applyValue,
        handleClear,
        showClearButton,
    };
}

function useTreeSelectState(props) {
    const { isSearchable = false, defaultExpandedKeys } = props;
    const defaultExpandedKeysRef = React.useRef(defaultExpandedKeys);
    defaultExpandedKeysRef.current = defaultExpandedKeys;
    const value = useTreeSelectValue(props);
    const [isOpen, setIsOpen] = React.useState(false);
    const [searchTerm, setSearchTerm] = React.useState("");
    const [expandedKeys, setExpandedKeys] = React.useState(defaultExpandedKeys ?? []);
    const prunedTreeData = React.useMemo(() => searchTerm.trim()
        ? pruneTree(value.treeData, searchTerm)
        : value.treeData, [value.treeData, searchTerm]);
    const effectiveExpandedKeys = React.useMemo(() => {
        if (!searchTerm)
            return expandedKeys;
        const allKeys = [];
        Tree.walkTree(prunedTreeData, node => {
            if (node.children?.length)
                allKeys.push(node.key);
        });
        return allKeys;
    }, [searchTerm, prunedTreeData]);
    const handleSelect = React.useCallback((keys, info) => {
        if (value.isDisabled || info.node.disabled)
            return;
        value.applyValue(keys[0] ?? "");
        setIsOpen(false);
        setSearchTerm("");
    }, [value.applyValue, value.isDisabled]);
    const handleOpenChange = React.useCallback((open) => {
        if (value.isDisabled)
            return;
        setIsOpen(open);
        if (!open) {
            setSearchTerm("");
            setExpandedKeys(defaultExpandedKeysRef.current ?? []);
        }
    }, [value.isDisabled]);
    const handleExpand = React.useCallback((keys) => setExpandedKeys(keys), []);
    return {
        ...value,
        isSearchable,
        isOpen,
        handleOpenChange,
        searchTerm,
        setSearchTerm,
        prunedTreeData,
        effectiveExpandedKeys,
        handleSelect,
        handleExpand,
    };
}

const DROPDOWN_HEIGHT = 256;
const SIZE_CONFIG = {
    small: { trigger: "min-h-7 px-2 py-0.5", text: "text-xs" },
    medium: { trigger: "min-h-8 px-2.5 py-1", text: "text-sm" },
    large: { trigger: "min-h-10 px-2.5 py-1.5", text: "text-sm" },
};

const TreeSelectTrigger = React.forwardRef(({ size, currentValue, selectedLabel, placeholder, isDisabled, error, showClearButton, handleClear, suffixIcon, className, ...rest }, ref) => (jsxRuntime.jsxs("button", { ref: ref, type: "button", disabled: isDisabled, ...rest, className: utils.cn("inline-flex w-full items-center gap-1 rounded-md border border-input bg-background outline-none", "hover:bg-accent focus:ring-1 focus:ring-ring", "disabled:pointer-events-none disabled:opacity-50", error && "border-destructive", SIZE_CONFIG[size].trigger, SIZE_CONFIG[size].text, className), children: [jsxRuntime.jsx("span", { className: utils.cn("flex-1 truncate text-left", !currentValue && "text-muted-foreground"), children: selectedLabel || placeholder || "" }), showClearButton && (jsxRuntime.jsx("span", { role: "button", tabIndex: -1, "aria-label": "Clear selection", className: "shrink-0 text-muted-foreground hover:text-foreground", onClick: handleClear, children: jsxRuntime.jsx(x.X, { className: "size-3.5" }) })), suffixIcon ?? jsxRuntime.jsx(chevronDown.ChevronDown, { className: "size-4 shrink-0 opacity-50" })] })));
TreeSelectTrigger.displayName = "TreeSelectTrigger";

const TreeSelect = React.forwardRef((props, ref) => {
    const s = useTreeSelectState(props);
    const { suffixIcon, switcherIcon, autoExpandParent, className } = props;
    return (jsxRuntime.jsx(SelectFieldWrapper.SelectFieldWrapper, { id: s.id, label: s.label, error: s.error, helpText: s.helpText, errorId: s.errorId, helpTextId: s.helpTextId, isDisabled: s.isDisabled, required: s.required, className: className, children: jsxRuntime.jsxs(primitives_Popover.Popover, { open: s.isOpen, onOpenChange: s.handleOpenChange, children: [jsxRuntime.jsx(primitives_Popover.PopoverTrigger, { asChild: true, children: jsxRuntime.jsx(TreeSelectTrigger, { ref: ref, currentValue: s.currentValue, error: s.error, handleClear: s.handleClear, isDisabled: s.isDisabled, placeholder: props.placeholder, selectedLabel: s.selectedLabel, showClearButton: s.showClearButton, size: s.size, suffixIcon: suffixIcon }) }), jsxRuntime.jsxs(primitives_Popover.PopoverContent, { align: "start", className: "w-[var(--radix-popover-trigger-width)] p-0", onOpenAutoFocus: e => {
                        if (s.isSearchable)
                            e.preventDefault();
                    }, children: [s.isSearchable && (jsxRuntime.jsx("div", { className: "border-b border-border px-2 py-1.5", children: jsxRuntime.jsx("input", { autoFocus: true, type: "text", className: utils.cn("w-full bg-transparent outline-none placeholder:text-muted-foreground", SIZE_CONFIG[s.size].text), placeholder: "Search...", value: s.searchTerm, onChange: e => s.setSearchTerm(e.target.value) }) })), s.prunedTreeData.length > 0 ? (jsxRuntime.jsx("div", { className: "p-1", children: jsxRuntime.jsx(Tree.Tree, { autoExpandParent: autoExpandParent, expandedKeys: s.effectiveExpandedKeys, height: DROPDOWN_HEIGHT, switcherIcon: switcherIcon, treeData: s.prunedTreeData, onExpand: s.handleExpand, onSelect: s.handleSelect }) })) : (jsxRuntime.jsx("div", { className: "py-6 text-center text-sm text-muted-foreground", children: "No results found." }))] })] }) }));
});
TreeSelect.displayName = "TreeSelect";

exports.TreeSelect = TreeSelect;
//# sourceMappingURL=TreeSelect-BoffO6qD.js.map
