"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: Object.getOwnPropertyDescriptor(all, name).get
    });
}
_export(exports, {
    get comboboxConfig () {
        return comboboxConfig;
    },
    get comboboxRoot () {
        return comboboxRoot;
    }
});
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
const _utils = require("../../utils");
const _hooks = require("../../hooks");
const _utils1 = require("./utils");
const _Comboboxtokens = require("./Combobox.tokens");
const _FloatingPopover = require("./FloatingPopover");
const _hooks1 = require("./hooks");
const _ui = require("./ui");
const _Comboboxstyles = require("./Combobox.styles");
const _base = require("./variations/_view/base");
const _base1 = require("./variations/_size/base");
const _base2 = require("./variations/_readOnly/base");
const _SelectNative = require("./ui/SelectNative/SelectNative");
const _Comboboxcontext = require("./Combobox.context");
function _getRequireWildcardCache(nodeInterop) {
    if (typeof WeakMap !== "function") return null;
    var cacheBabelInterop = new WeakMap();
    var cacheNodeInterop = new WeakMap();
    return (_getRequireWildcardCache = function(nodeInterop) {
        return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
    })(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
    if (!nodeInterop && obj && obj.__esModule) {
        return obj;
    }
    if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
        return {
            default: obj
        };
    }
    var cache = _getRequireWildcardCache(nodeInterop);
    if (cache && cache.has(obj)) {
        return cache.get(obj);
    }
    var newObj = {
        __proto__: null
    };
    var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
    for(var key in obj){
        if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
            var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
            if (desc && (desc.get || desc.set)) {
                Object.defineProperty(newObj, key, desc);
            } else {
                newObj[key] = obj[key];
            }
        }
    }
    newObj.default = obj;
    if (cache) {
        cache.set(obj, newObj);
    }
    return newObj;
}
const comboboxRoot = (Root)=>/*#__PURE__*/ (0, _react.forwardRef)((props, ref)=>{
        const { /* Config */ view, size, chipView, hintView, hintSize, /* Target */ chipClickArea = 'full', contentLeft, contentRight, placeholder, helperText, label, labelPlacement, keepPlaceholder, /* IsMultiple */ multiple, value: outerValue, defaultValue, onChange: outerOnChange, isTargetAmount, targetAmount, renderValue, name, /* Basic */ items, treeView = false, arrowPlacement = 'left', placement = 'bottom-start', variant = 'normal', zIndex, listMaxHeight, listWidth, portal, textBefore, textAfter, renderItem, renderSelectionIcon, filter, closeAfterSelect: outerCloseAfterSelect, onChangeValue, filterValue, onScroll, onToggle, beforeList, afterList, virtual = false, mode = 'default', emptyStateDescription, flip, shift, singleLine, readOnly = false, disabled = false, alwaysOpened = false, /* Private */ _offset, /* Rest */ ...rest } = props;
        // Deep copy массива items с добавлением parent-ноды родителя.
        const transformedItems = (0, _react.useMemo)(()=>(0, _utils1.initialItemsTransform)(items || []), [
            items
        ]);
        // Создаем структуры для быстрой работы с полным деревом.
        const [valueToCheckedMap, valueToItemMap, valueToPathMap] = (0, _hooks1.useSelectionMaps)(transformedItems);
        /**
         * Refs
         */ const floatingPopoverRef = (0, _react.useRef)(null);
        const treeId = (0, _utils.safeUseId)();
        const listWrapperRef = (0, _react.useRef)(null);
        const rootRef = (0, _react.useRef)(null);
        const inputRef = (0, _react.useRef)(null);
        const inputForkRef = (0, _hooks.useForkRef)(inputRef, ref);
        /**
         * Hooks
         */ const nativeMode = Boolean(name && !(0, _utils1.hasOuterValue)(outerValue));
        const { value, handleChange, textValue, setTextValue } = (0, _hooks1.useValue)({
            outerValue,
            outerOnChange,
            defaultValue,
            multiple,
            nativeMode,
            valueToItemMap,
            renderValue,
            onChangeValue
        });
        const currentLabel = (0, _utils1.getTextValue)(multiple, value, valueToItemMap, renderValue);
        const { filteredItems, filteredMaps: { pathMap: filteredPathMap, focusedToValueMap: filteredFocusedToValueMap, valueToPathMap: filteredValueToPathMap } } = (0, _hooks1.useComboboxItems)({
            items: transformedItems,
            textValue,
            currentLabel,
            filter
        });
        const { path, treePath, focusedPath, dispatchPath, dispatchTreePath, dispatchFocusedPath, handleListToggle, resetListState, isListOpened } = (0, _hooks1.useListState)({
            disabled,
            readOnly,
            onToggle,
            multiple,
            alwaysOpened,
            renderValue,
            rootRef,
            value,
            valueToItemMap,
            setTextValue
        });
        const { checked, handleCheckboxChange, handleItemClick, handlePressDown } = (0, _hooks1.useCheckedState)({
            multiple,
            mode,
            value,
            valueToCheckedMap,
            valueToItemMap,
            closeAfterSelect: outerCloseAfterSelect ?? !multiple,
            resetListState,
            handleChange
        });
        const { onKeyDown } = (0, _hooks1.useKeyNavigation)({
            focusedPath,
            dispatchFocusedPath,
            path,
            dispatchPath,
            pathMap: filteredPathMap,
            focusedToValueMap: filteredFocusedToValueMap,
            handleListToggle,
            handlePressDown,
            setTextValue,
            multiple,
            value,
            textValue,
            valueToItemMap,
            treePath,
            dispatchTreePath,
            treeView,
            valueToPathMap: filteredValueToPathMap,
            items: filteredItems,
            disabled,
            readOnly
        });
        /**
         * Handlers
         */ /* Обработчик изменения значения в инпуте */ const handleTextValueChange = (e)=>{
            if (!filterValue || filterValue(e.target.value)) {
                setTextValue(e.target.value);
            }
            dispatchPath({
                type: 'opened_first_level'
            });
            dispatchFocusedPath({
                type: 'reset'
            });
        };
        const handleClickArrow = (e)=>{
            handleListToggle(!isListOpened);
            // При клике на иконку закрытия фокус не должен становиться в инпут.
            e.stopPropagation();
        };
        /* Обработчик клика на таргет */ const handleTargetClick = ()=>{
            if (!isListOpened) {
                handleListToggle(true);
            }
        };
        /* Метод получения чипов в определенном формате */ const getChips = ()=>{
            if (multiple && Array.isArray(value)) {
                if (value.length === 0) return [];
                if (isTargetAmount) {
                    return [
                        {
                            value: '_removeAll',
                            label: `Выбрано ${targetAmount || value.length}`,
                            disabled: value.every((val)=>valueToItemMap?.get(val)?.disabled)
                        }
                    ];
                }
                return value.map((value)=>{
                    const currentLabel = renderValue ? renderValue(valueToItemMap.get(value) || {
                        value,
                        label: value
                    }) : valueToItemMap.get(value)?.label || value.toString();
                    return {
                        value,
                        label: currentLabel,
                        disabled: valueToItemMap.get(value)?.disabled || false
                    };
                });
            }
            return [];
        };
        /* Обработчик чипов */ const handleChipClick = (chip)=>{
            if (readOnly || !Array.isArray(value)) return;
            if (isTargetAmount) {
                // При закрытии чипа в режиме isTargetAmount в value оставляем только disabled-элементы
                handleChange(value.filter((val)=>valueToItemMap?.get(val)?.disabled), null);
            } else {
                handleChange(value.filter((val)=>val !== chip.value), valueToItemMap.get(chip.value) || {
                    value: chip.value,
                    label: chip.label
                });
            }
        };
        /**
         * Effects
         */ /* Логика работы при клике за пределами выпадающего списка */ (0, _hooks.useOutsideClick)(()=>{
            if (!isListOpened || alwaysOpened) {
                return;
            }
            handleListToggle(false);
        }, [
            floatingPopoverRef,
            listWrapperRef
        ]);
        // Эффект для исключительных случаев, когда нужно обновить значение textValue при изменении items,
        // но только если значение textValue совпадает с value в item.
        (0, _react.useLayoutEffect)(()=>{
            if (!multiple && value && valueToItemMap.get(value)?.value === textValue) {
                setTextValue(valueToItemMap.get(value)?.label || value.toString());
            }
        }, [
            items
        ]);
        // При изменении value нужно возвращать значение в инпуте к исходному.
        (0, _hooks.useDidMountLayoutEffect)(()=>{
            setTextValue((0, _utils1.getTextValue)(multiple, value, valueToItemMap, renderValue));
        }, [
            value
        ]);
        // Эффект для раскрытия дерева при поиске.
        (0, _react.useLayoutEffect)(()=>{
            if (treeView) {
                // Если поле ввода стало пустым или если пользователь выбирает элемент,
                // то скрываем все узлы дерева и выходим из эффекта.
                if (textValue === '' || textValue === currentLabel) {
                    dispatchTreePath({
                        type: 'reset'
                    });
                    return;
                }
                // Иначе раскрываем все узлы, когда пользователь начинает вводить текст в поле ввода.
                dispatchTreePath({
                    type: 'expand_by_key',
                    value: {
                        filteredItems,
                        filterCb: filter || _utils1.defaultFilter,
                        textValue
                    }
                });
            }
        }, [
            textValue
        ]);
        /**
         * Vars
         */ const activeDescendantItemValue = (0, _hooks1.getItemByFocused)(focusedPath, filteredFocusedToValueMap)?.value || '';
        const withArrowInverse = isListOpened ? _Comboboxtokens.classes.arrowInverse : undefined;
        return /*#__PURE__*/ _react.default.createElement(Root, {
            size: size,
            view: view,
            labelPlacement: labelPlacement,
            chipView: chipView,
            disabled: disabled,
            readOnly: readOnly,
            name: name,
            hintView: hintView,
            hintSize: hintSize,
            ref: rootRef
        }, nativeMode && /*#__PURE__*/ _react.default.createElement(_SelectNative.SelectNative, {
            items: valueToItemMap,
            name: name,
            value: value,
            multiple: multiple,
            handleChange: handleChange,
            outerOnChange: outerOnChange,
            ref: ref
        }), /*#__PURE__*/ _react.default.createElement("div", null, /*#__PURE__*/ _react.default.createElement(_Comboboxcontext.Context.Provider, {
            value: {
                focusedPath,
                checked,
                multiple,
                size,
                handleCheckboxChange,
                handleItemClick,
                variant,
                renderItem,
                renderSelectionIcon,
                treeId,
                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                // @ts-ignore
                // eslint-disable-next-line no-underscore-dangle
                _checkboxAppearance: rest._checkboxAppearance,
                treePath,
                dispatchTreePath,
                arrowPlacement,
                valueToPathMap,
                singleLine
            }
        }, /*#__PURE__*/ _react.default.createElement(_FloatingPopover.FloatingPopover, {
            ref: floatingPopoverRef,
            opened: isListOpened,
            placement: placement,
            portal: portal,
            listWidth: listWidth,
            offset: _offset,
            target: (referenceRef)=>/*#__PURE__*/ _react.default.createElement("div", {
                    onClick: handleTargetClick
                }, /*#__PURE__*/ _react.default.createElement(_ui.StyledTextField, {
                    ref: name ? inputRef : inputForkRef,
                    inputWrapperRef: referenceRef,
                    opened: isListOpened,
                    value: textValue,
                    onChange: handleTextValueChange,
                    size: size,
                    view: view,
                    disabled: disabled,
                    readOnly: readOnly,
                    label: label,
                    placeholder: placeholder,
                    contentLeft: contentLeft,
                    contentRight: contentRight || contentRight !== undefined ? contentRight : /*#__PURE__*/ _react.default.createElement(_Comboboxstyles.IconArrowWrapper, {
                        disabled: disabled,
                        readOnly: readOnly,
                        onClick: handleClickArrow,
                        className: _Comboboxtokens.classes.comboboxTargetArrow
                    }, /*#__PURE__*/ _react.default.createElement(_Comboboxstyles.StyledArrow, {
                        color: "inherit",
                        size: (0, _utils1.sizeToIconSize)(size),
                        className: withArrowInverse
                    })),
                    textBefore: textBefore,
                    textAfter: textAfter,
                    onKeyDown: onKeyDown,
                    leftHelper: helperText && /*#__PURE__*/ _react.default.createElement(_Comboboxstyles.StyledLeftHelper, {
                        onClick: (e)=>e.stopPropagation()
                    }, helperText),
                    role: "combobox",
                    "aria-autocomplete": "list",
                    "aria-controls": `${treeId}_tree_level_1`,
                    "aria-expanded": isListOpened,
                    "aria-activedescendant": activeDescendantItemValue ? (0, _utils1.getItemId)(treeId, activeDescendantItemValue) : '',
                    labelPlacement: labelPlacement,
                    keepPlaceholder: keepPlaceholder,
                    chipView: chipView,
                    ...multiple ? {
                        enumerationType: 'chip',
                        _chipClickArea: chipClickArea,
                        _chips: getChips(),
                        _onChipCloseClick: handleChipClick
                    } : {
                        enumerationType: 'plain'
                    },
                    ...rest,
                    _onEnterDisabled: true // Пропс для отключения обработчика Enter внутри Textfield
                })),
            zIndex: zIndex,
            isInner: false,
            shift: shift,
            flip: flip
        }, /*#__PURE__*/ _react.default.createElement(Root, {
            size: size,
            view: view,
            labelPlacement: labelPlacement,
            chipView: chipView,
            disabled: disabled,
            readOnly: readOnly,
            name: name
        }, treeView ? /*#__PURE__*/ _react.default.createElement(_ui.TreeList, {
            items: filteredItems,
            listMaxHeight: listMaxHeight,
            onScroll: virtual ? undefined : onScroll,
            virtual: virtual,
            beforeList: beforeList,
            afterList: afterList,
            emptyStateDescription: emptyStateDescription
        }) : /*#__PURE__*/ _react.default.createElement(_Comboboxstyles.ListWrapper, {
            ref: listWrapperRef,
            listWidth: listWidth
        }, /*#__PURE__*/ _react.default.createElement(_Comboboxstyles.Ul, {
            role: "tree",
            id: `${treeId}_tree_level_1`,
            "aria-multiselectable": Boolean(multiple),
            listMaxHeight: listMaxHeight,
            virtual: virtual,
            onScroll: virtual ? undefined : onScroll
        }, beforeList, props.multiple && props.selectAllOptions && // TODO: #2004
        /*#__PURE__*/ _react.default.createElement(_ui.SelectAll, {
            selectAllOptions: props.selectAllOptions,
            variant: variant
        }), (0, _utils.isEmpty)(filteredItems) ? /*#__PURE__*/ _react.default.createElement(_Comboboxstyles.StyledEmptyState, {
            className: _Comboboxtokens.classes.emptyStateWrapper,
            description: emptyStateDescription || 'Ничего не найдено'
        }) : /*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, virtual ? /*#__PURE__*/ _react.default.createElement(_ui.VirtualList, {
            items: filteredItems,
            listMaxHeight: listMaxHeight,
            onScroll: onScroll,
            renderItem: (item, index)=>/*#__PURE__*/ _react.default.createElement(_ui.Inner, {
                    item: item,
                    currentLevel: 0,
                    path: [
                        'root'
                    ],
                    dispatchPath: dispatchPath,
                    index: index,
                    listWidth: listWidth,
                    portal: listWrapperRef,
                    shift: shift,
                    flip: flip
                })
        }) : filteredItems.map((item, index)=>/*#__PURE__*/ _react.default.createElement(_ui.Inner, {
                key: `${index}/0`,
                item: item,
                currentLevel: 0,
                path: path,
                dispatchPath: dispatchPath,
                index: index,
                listWidth: listWidth,
                portal: listWrapperRef,
                shift: shift,
                flip: flip
            }))), afterList)))))));
    });
const comboboxConfig = {
    name: 'Select',
    tag: 'div',
    layout: comboboxRoot,
    base: _Comboboxstyles.base,
    variations: {
        view: {
            css: _base.base
        },
        size: {
            css: _base1.base
        },
        readOnly: {
            css: _base2.base
        }
    },
    defaults: {
        view: 'default',
        size: 'm',
        labelPlacement: 'outer',
        chipView: 'secondary'
    }
};
