/**
 * DevExtreme (cjs/ui/drop_down_button.js)
 * Version: 23.2.6 (build 24140-0112)
 * Build date: Sun May 19 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
exports.default = void 0;
var _renderer = _interopRequireDefault(require("../core/renderer"));
var _ui = _interopRequireDefault(require("./widget/ui.widget"));
var _function_template = require("../core/templates/function_template");
var _component_registrator = _interopRequireDefault(require("../core/component_registrator"));
var _button_group = _interopRequireDefault(require("./button_group"));
var _ui2 = _interopRequireDefault(require("./popup/ui.popup"));
var _list_light = _interopRequireDefault(require("./list_light"));
var _data = require("../core/utils/data");
var _element = require("../core/element");
var _icon = require("../core/utils/icon");
var _data_helper = _interopRequireDefault(require("../data_helper"));
var _data_source = require("../data/data_source/data_source");
var _array_store = _interopRequireDefault(require("../data/array_store"));
var _deferred = require("../core/utils/deferred");
var _extend = require("../core/utils/extend");
var _type = require("../core/utils/type");
var _common = require("../core/utils/common");
var _guid = _interopRequireDefault(require("../core/guid"));
var _utils = require("./drop_down_editor/utils");
var _message = _interopRequireDefault(require("../localization/message"));

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    }
}

function _extends() {
    _extends = Object.assign ? Object.assign.bind() : function(target) {
        for (var i = 1; i < arguments.length; i++) {
            var source = arguments[i];
            for (var key in source) {
                if (Object.prototype.hasOwnProperty.call(source, key)) {
                    target[key] = source[key]
                }
            }
        }
        return target
    };
    return _extends.apply(this, arguments)
}
const DROP_DOWN_BUTTON_CLASS = "dx-dropdownbutton";
const DROP_DOWN_BUTTON_CONTENT = "dx-dropdownbutton-content";
const DROP_DOWN_BUTTON_ACTION_CLASS = "dx-dropdownbutton-action";
const DROP_DOWN_BUTTON_TOGGLE_CLASS = "dx-dropdownbutton-toggle";
const DROP_DOWN_BUTTON_HAS_ARROW_CLASS = "dx-dropdownbutton-has-arrow";
const DROP_DOWN_BUTTON_POPUP_WRAPPER_CLASS = "dx-dropdownbutton-popup-wrapper";
const DROP_DOWN_EDITOR_OVERLAY_CLASS = "dx-dropdowneditor-overlay";
const DX_BUTTON_CLASS = "dx-button";
const DX_BUTTON_TEXT_CLASS = "dx-button-text";
const DX_ICON_RIGHT_CLASS = "dx-icon-right";
const DropDownButton = _ui.default.inherit({
    _getDefaultOptions() {
        return (0, _extend.extend)(this.callBase(), {
            itemTemplate: "item",
            keyExpr: "this",
            displayExpr: void 0,
            selectedItem: null,
            selectedItemKey: null,
            stylingMode: "outlined",
            deferRendering: true,
            noDataText: _message.default.format("dxCollectionWidget-noDataText"),
            useSelectMode: false,
            splitButton: false,
            showArrowIcon: true,
            text: "",
            type: "normal",
            icon: void 0,
            onButtonClick: null,
            onSelectionChanged: null,
            onItemClick: null,
            opened: false,
            items: null,
            dataSource: null,
            focusStateEnabled: true,
            hoverStateEnabled: true,
            dropDownOptions: {},
            dropDownContentTemplate: "content",
            wrapItemText: false,
            useItemTextAsTitle: true,
            grouped: false,
            groupTemplate: "group",
            buttonGroupOptions: {}
        })
    },
    _setOptionsByReference() {
        this.callBase();
        (0, _extend.extend)(this._optionsByReference, {
            selectedItem: true
        })
    },
    _init() {
        this.callBase();
        this._createItemClickAction();
        this._createActionClickAction();
        this._createSelectionChangedAction();
        this._initDataSource();
        this._compileKeyGetter();
        this._compileDisplayGetter();
        this._itemsToDataSource(this.option("items"));
        this._options.cache("buttonGroupOptions", this.option("buttonGroupOptions"));
        this._options.cache("dropDownOptions", this.option("dropDownOptions"))
    },
    _initTemplates() {
        this._templateManager.addDefaultTemplates({
            content: new _function_template.FunctionTemplate(options => {
                const $popupContent = (0, _renderer.default)(options.container);
                const $listContainer = (0, _renderer.default)("<div>").appendTo($popupContent);
                this._list = this._createComponent($listContainer, _list_light.default, this._listOptions());
                this._list.registerKeyHandler("escape", this._escHandler.bind(this));
                this._list.registerKeyHandler("tab", this._escHandler.bind(this));
                this._list.registerKeyHandler("leftArrow", this._escHandler.bind(this));
                this._list.registerKeyHandler("rightArrow", this._escHandler.bind(this))
            })
        });
        this.callBase()
    },
    _itemsToDataSource: function(value) {
        if (!this._dataSource) {
            this._dataSource = new _data_source.DataSource({
                store: new _array_store.default({
                    key: this._getKey(),
                    data: value
                }),
                pageSize: 0
            })
        }
    },
    _getKey: function() {
        var _this$_dataSource;
        const keyExpr = this.option("keyExpr");
        const storeKey = null === (_this$_dataSource = this._dataSource) || void 0 === _this$_dataSource ? void 0 : _this$_dataSource.key();
        return (0, _type.isDefined)(storeKey) && (!(0, _type.isDefined)(keyExpr) || "this" === keyExpr) ? storeKey : keyExpr
    },
    _compileKeyGetter() {
        this._keyGetter = (0, _data.compileGetter)(this._getKey())
    },
    _compileDisplayGetter() {
        this._displayGetter = (0, _data.compileGetter)(this.option("displayExpr"))
    },
    _initMarkup() {
        this.callBase();
        this.$element().addClass("dx-dropdownbutton");
        this._renderButtonGroup();
        this._updateArrowClass();
        if ((0, _type.isDefined)(this.option("selectedItemKey"))) {
            this._loadSelectedItem().done(this._updateActionButton.bind(this))
        }
    },
    _renderFocusTarget: _common.noop,
    _render() {
        if (!this.option("deferRendering") || this.option("opened")) {
            this._renderPopup()
        }
        this.callBase()
    },
    _renderContentImpl() {
        if (this._popup) {
            this._renderPopupContent()
        }
        return this.callBase()
    },
    _loadSelectedItem() {
        var _this$_loadSingleDefe;
        null === (_this$_loadSingleDefe = this._loadSingleDeferred) || void 0 === _this$_loadSingleDefe ? void 0 : _this$_loadSingleDefe.reject();
        const d = new _deferred.Deferred;
        if (this._list && void 0 !== this._lastSelectedItemData) {
            const cachedResult = this.option("useSelectMode") ? this._list.option("selectedItem") : this._lastSelectedItemData;
            return d.resolve(cachedResult)
        }
        this._lastSelectedItemData = void 0;
        const selectedItemKey = this.option("selectedItemKey");
        this._loadSingle(this._getKey(), selectedItemKey).done(d.resolve).fail(() => {
            d.resolve(null)
        });
        this._loadSingleDeferred = d;
        return d.promise()
    },
    _createActionClickAction() {
        this._actionClickAction = this._createActionByOption("onButtonClick")
    },
    _createSelectionChangedAction() {
        this._selectionChangedAction = this._createActionByOption("onSelectionChanged")
    },
    _createItemClickAction() {
        this._itemClickAction = this._createActionByOption("onItemClick")
    },
    _fireSelectionChangedAction(_ref) {
        let {
            previousValue: previousValue,
            value: value
        } = _ref;
        this._selectionChangedAction({
            item: value,
            previousItem: previousValue
        })
    },
    _fireItemClickAction(_ref2) {
        let {
            event: event,
            itemElement: itemElement,
            itemData: itemData
        } = _ref2;
        return this._itemClickAction({
            event: event,
            itemElement: itemElement,
            itemData: this._actionItem || itemData
        })
    },
    _actionButtonConfig() {
        const {
            icon: icon,
            text: text,
            type: type
        } = this.option();
        return {
            text: text,
            icon: icon,
            type: type,
            elementAttr: {
                class: "dx-dropdownbutton-action"
            }
        }
    },
    _getButtonGroupItems() {
        const {
            splitButton: splitButton,
            type: type
        } = this.option();
        const items = [];
        items.push(this._actionButtonConfig());
        if (splitButton) {
            items.push({
                icon: "spindown",
                type: type,
                elementAttr: {
                    class: "dx-dropdownbutton-toggle"
                }
            })
        }
        return items
    },
    _buttonGroupItemClick(_ref3) {
        let {
            event: event,
            itemData: itemData
        } = _ref3;
        const isActionButton = "dx-dropdownbutton-action" === itemData.elementAttr.class;
        const isToggleButton = "dx-dropdownbutton-toggle" === itemData.elementAttr.class;
        if (isToggleButton) {
            this.toggle()
        } else if (isActionButton) {
            this._actionClickAction({
                event: event,
                selectedItem: this.option("selectedItem")
            });
            if (!this.option("splitButton")) {
                this.toggle()
            }
        }
    },
    _buttonGroupOptions() {
        const {
            splitButton: splitButton,
            showArrowIcon: showArrowIcon,
            focusStateEnabled: focusStateEnabled,
            hoverStateEnabled: hoverStateEnabled,
            stylingMode: stylingMode,
            accessKey: accessKey,
            tabIndex: tabIndex
        } = this.option();
        const buttonTemplate = splitButton || !showArrowIcon ? "content" : (_ref4, buttonContent) => {
            let {
                text: text,
                icon: icon
            } = _ref4;
            const $firstIcon = (0, _icon.getImageContainer)(icon);
            const $textContainer = text ? (0, _renderer.default)("<span>").text(text).addClass("dx-button-text") : void 0;
            const $secondIcon = (0, _icon.getImageContainer)("spindown").addClass("dx-icon-right");
            (0, _renderer.default)(buttonContent).append($firstIcon, $textContainer, $secondIcon)
        };
        return (0, _extend.extend)({
            items: this._getButtonGroupItems(),
            onItemClick: this._buttonGroupItemClick.bind(this),
            width: "100%",
            height: "100%",
            selectionMode: "none",
            onKeyboardHandled: e => this._keyboardHandler(e),
            buttonTemplate: buttonTemplate,
            focusStateEnabled: focusStateEnabled,
            hoverStateEnabled: hoverStateEnabled,
            stylingMode: stylingMode,
            accessKey: accessKey,
            tabIndex: tabIndex
        }, this._options.cache("buttonGroupOptions"))
    },
    _renderPopupContent() {
        const $content = this._popup.$content();
        const template = this._getTemplateByOption("dropDownContentTemplate");
        $content.empty();
        this._popupContentId = "dx-" + new _guid.default;
        this.setAria("id", this._popupContentId, $content);
        return template.render({
            container: (0, _element.getPublicElement)($content),
            model: this.option("items") || this._dataSource
        })
    },
    _popupOptions() {
        const horizontalAlignment = this.option("rtlEnabled") ? "right" : "left";
        return (0, _extend.extend)({
            dragEnabled: false,
            focusStateEnabled: false,
            deferRendering: this.option("deferRendering"),
            hideOnOutsideClick: e => {
                const $element = this.$element();
                const $buttonClicked = (0, _renderer.default)(e.target).closest(".".concat("dx-dropdownbutton"));
                return !$buttonClicked.is($element)
            },
            showTitle: false,
            animation: {
                show: {
                    type: "fade",
                    duration: 0,
                    from: 0,
                    to: 1
                },
                hide: {
                    type: "fade",
                    duration: 400,
                    from: 1,
                    to: 0
                }
            },
            _ignoreFunctionValueDeprecation: true,
            width: () => (0, _utils.getElementWidth)(this.$element()),
            height: "auto",
            shading: false,
            position: {
                of: this.$element(),
                collision: "flipfit",
                my: horizontalAlignment + " top",
                at: horizontalAlignment + " bottom"
            },
            _wrapperClassExternal: "dx-dropdowneditor-overlay"
        }, this._options.cache("dropDownOptions"), {
            visible: this.option("opened")
        })
    },
    _listOptions() {
        const selectedItemKey = this.option("selectedItemKey");
        const useSelectMode = this.option("useSelectMode");
        return {
            selectionMode: useSelectMode ? "single" : "none",
            wrapItemText: this.option("wrapItemText"),
            focusStateEnabled: this.option("focusStateEnabled"),
            hoverStateEnabled: this.option("hoverStateEnabled"),
            useItemTextAsTitle: this.option("useItemTextAsTitle"),
            onContentReady: () => this._fireContentReadyAction(),
            selectedItemKeys: (0, _type.isDefined)(selectedItemKey) && useSelectMode ? [selectedItemKey] : [],
            grouped: this.option("grouped"),
            groupTemplate: this.option("groupTemplate"),
            keyExpr: this._getKey(),
            noDataText: this.option("noDataText"),
            displayExpr: this.option("displayExpr"),
            itemTemplate: this.option("itemTemplate"),
            items: this.option("items"),
            dataSource: this._dataSource,
            onItemClick: e => {
                if (!this.option("useSelectMode")) {
                    this._lastSelectedItemData = e.itemData
                }
                this.option("selectedItemKey", this._keyGetter(e.itemData));
                const actionResult = this._fireItemClickAction(e);
                if (false !== actionResult) {
                    this.toggle(false);
                    this._buttonGroup.focus()
                }
            }
        }
    },
    _upDownKeyHandler() {
        if (this._popup && this._popup.option("visible") && this._list) {
            this._list.focus()
        } else {
            this.open()
        }
        return true
    },
    _escHandler() {
        this.close();
        this._buttonGroup.focus();
        return true
    },
    _tabHandler() {
        this.close();
        return true
    },
    _renderPopup() {
        const $popup = (0, _renderer.default)("<div>");
        this.$element().append($popup);
        this._popup = this._createComponent($popup, _ui2.default, this._popupOptions());
        this._popup.$content().addClass(DROP_DOWN_BUTTON_CONTENT);
        this._popup.$wrapper().addClass("dx-dropdownbutton-popup-wrapper");
        this._popup.on("hiding", this._popupHidingHandler.bind(this));
        this._popup.on("showing", this._popupShowingHandler.bind(this));
        this._bindInnerWidgetOptions(this._popup, "dropDownOptions")
    },
    _popupHidingHandler() {
        this.option("opened", false);
        this._updateAriaAttributes(false)
    },
    _popupOptionChanged: function(args) {
        const options = _ui.default.getOptionsFromContainer(args);
        this._setPopupOption(options);
        const optionsKeys = Object.keys(options);
        if (-1 !== optionsKeys.indexOf("width") || -1 !== optionsKeys.indexOf("height")) {
            this._dimensionChanged()
        }
    },
    _dimensionChanged: function() {
        const popupWidth = (0, _utils.getSizeValue)(this.option("dropDownOptions.width"));
        if (void 0 === popupWidth) {
            this._setPopupOption("width", () => (0, _utils.getElementWidth)(this.$element()))
        }
    },
    _setPopupOption: function(optionName, value) {
        this._setWidgetOption("_popup", arguments)
    },
    _popupShowingHandler() {
        this.option("opened", true);
        this._updateAriaAttributes(true)
    },
    _setElementAria(value) {
        const elementAria = {
            owns: value ? this._popupContentId : void 0
        };
        this.setAria(elementAria, this.$element())
    },
    _setButtonsAria(value) {
        const commonButtonAria = {
            expanded: value,
            haspopup: "listbox"
        };
        const firstButtonAria = {};
        if (!this.option("text")) {
            firstButtonAria.label = "dropdownbutton"
        }
        this._getButtons().each((index, $button) => {
            if (0 === index) {
                this.setAria(_extends({}, firstButtonAria, commonButtonAria), (0, _renderer.default)($button))
            } else {
                this.setAria(commonButtonAria, (0, _renderer.default)($button))
            }
        })
    },
    _updateAriaAttributes(value) {
        this._setElementAria(value);
        this._setButtonsAria(value)
    },
    _getButtons() {
        return this._buttonGroup.$element().find(".".concat("dx-button"))
    },
    _renderButtonGroup() {
        const $buttonGroup = this._buttonGroup && this._buttonGroup.$element() || (0, _renderer.default)("<div>");
        if (!this._buttonGroup) {
            this.$element().append($buttonGroup)
        }
        this._buttonGroup = this._createComponent($buttonGroup, _button_group.default, this._buttonGroupOptions());
        this._buttonGroup.registerKeyHandler("downArrow", this._upDownKeyHandler.bind(this));
        this._buttonGroup.registerKeyHandler("tab", this._tabHandler.bind(this));
        this._buttonGroup.registerKeyHandler("upArrow", this._upDownKeyHandler.bind(this));
        this._buttonGroup.registerKeyHandler("escape", this._escHandler.bind(this));
        this._bindInnerWidgetOptions(this._buttonGroup, "buttonGroupOptions");
        this._updateAriaAttributes(this.option("opened"))
    },
    _updateArrowClass() {
        const hasArrow = this.option("splitButton") || this.option("showArrowIcon");
        this.$element().toggleClass("dx-dropdownbutton-has-arrow", hasArrow)
    },
    toggle(visible) {
        if (!this._popup) {
            this._renderPopup();
            this._renderContent()
        }
        return this._popup.toggle(visible)
    },
    open() {
        return this.toggle(true)
    },
    close() {
        return this.toggle(false)
    },
    _setListOption(name, value) {
        this._list && this._list.option(name, value)
    },
    _getDisplayValue(item) {
        const isPrimitiveItem = !(0, _type.isPlainObject)(item);
        const displayValue = isPrimitiveItem ? item : this._displayGetter(item);
        return !(0, _type.isPlainObject)(displayValue) ? String((0, _common.ensureDefined)(displayValue, "")) : ""
    },
    _updateActionButton(selectedItem) {
        if (this.option("useSelectMode")) {
            this.option({
                text: this._getDisplayValue(selectedItem),
                icon: (0, _type.isPlainObject)(selectedItem) ? selectedItem.icon : void 0
            })
        }
        this._setOptionWithoutOptionChange("selectedItem", selectedItem);
        this._setOptionWithoutOptionChange("selectedItemKey", this._keyGetter(selectedItem))
    },
    _clean() {
        this._list && this._list.$element().remove();
        this._popup && this._popup.$element().remove()
    },
    _selectedItemKeyChanged(value) {
        this._setListOption("selectedItemKeys", this.option("useSelectMode") && (0, _type.isDefined)(value) ? [value] : []);
        const previousItem = this.option("selectedItem");
        this._loadSelectedItem().done(selectedItem => {
            this._updateActionButton(selectedItem);
            if (this._displayGetter(previousItem) !== this._displayGetter(selectedItem)) {
                this._fireSelectionChangedAction({
                    previousValue: previousItem,
                    value: selectedItem
                })
            }
        })
    },
    _updateButtonGroup(name, value) {
        this._buttonGroup.option(name, value);
        this._updateAriaAttributes(this.option("opened"))
    },
    _actionButtonOptionChanged(_ref5) {
        let {
            name: name,
            value: value
        } = _ref5;
        const newConfig = {};
        newConfig[name] = value;
        this._updateButtonGroup("items[0]", (0, _extend.extend)({}, this._actionButtonConfig(), newConfig));
        this._popup && this._popup.repaint()
    },
    _selectModeChanged(value) {
        if (value) {
            this._setListOption("selectionMode", "single");
            const selectedItemKey = this.option("selectedItemKey");
            this._setListOption("selectedItemKeys", (0, _type.isDefined)(selectedItemKey) ? [selectedItemKey] : []);
            this._selectedItemKeyChanged(this.option("selectedItemKey"))
        } else {
            this._setListOption("selectionMode", "none");
            this.option({
                selectedItemKey: void 0,
                selectedItem: void 0
            });
            this._actionButtonOptionChanged({
                text: this.option("text")
            })
        }
    },
    _updateItemCollection(optionName) {
        const selectedItemKey = this.option("selectedItemKey");
        this._setListOption("selectedItem", null);
        this._setWidgetOption("_list", [optionName]);
        if ((0, _type.isDefined)(selectedItemKey)) {
            this._loadSelectedItem().done(selectedItem => {
                this._setListOption("selectedItemKeys", [selectedItemKey]);
                this._setListOption("selectedItem", selectedItem)
            }).fail(error => {
                this._setListOption("selectedItemKeys", [])
            }).always(this._updateActionButton.bind(this))
        }
    },
    _updateDataSource: function() {
        let items = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : this._dataSource.items();
        this._dataSource = void 0;
        this._itemsToDataSource(items);
        this._updateKeyExpr()
    },
    _updateKeyExpr: function() {
        this._compileKeyGetter();
        this._setListOption("keyExpr", this._getKey())
    },
    focus: function() {
        this._buttonGroup.focus()
    },
    _optionChanged(args) {
        var _this$_popup;
        const {
            name: name,
            value: value
        } = args;
        switch (name) {
            case "useSelectMode":
                this._selectModeChanged(value);
                break;
            case "splitButton":
                this._updateArrowClass();
                this._renderButtonGroup();
                break;
            case "displayExpr":
                this._compileDisplayGetter();
                this._setListOption(name, value);
                this._updateActionButton(this.option("selectedItem"));
                break;
            case "keyExpr":
                this._updateDataSource();
                break;
            case "buttonGroupOptions":
                this._innerWidgetOptionChanged(this._buttonGroup, args);
                break;
            case "dropDownOptions":
                if ("dropDownOptions.visible" === args.fullName) {
                    break
                }
                if (void 0 !== args.value.visible) {
                    delete args.value.visible
                }
                this._popupOptionChanged(args);
                this._innerWidgetOptionChanged(this._popup, args);
                break;
            case "opened":
                this.toggle(value);
                break;
            case "focusStateEnabled":
            case "hoverStateEnabled":
                this._setListOption(name, value);
                this._updateButtonGroup(name, value);
                this.callBase(args);
                break;
            case "items":
                this._updateDataSource(this.option("items"));
                this._updateItemCollection(name);
                break;
            case "dataSource":
                if (Array.isArray(value)) {
                    this._updateDataSource(this.option("dataSource"))
                } else {
                    this._initDataSource();
                    this._updateKeyExpr()
                }
                this._updateItemCollection(name);
                break;
            case "icon":
            case "text":
                this._actionButtonOptionChanged(args);
                break;
            case "showArrowIcon":
                this._updateArrowClass();
                this._renderButtonGroup();
                this._popup && this._popup.repaint();
                break;
            case "width":
            case "height":
                this.callBase(args);
                null === (_this$_popup = this._popup) || void 0 === _this$_popup ? void 0 : _this$_popup.repaint();
                break;
            case "stylingMode":
                this._updateButtonGroup(name, value);
                break;
            case "type":
                this._updateButtonGroup("items", this._getButtonGroupItems());
                break;
            case "itemTemplate":
            case "grouped":
            case "noDataText":
            case "groupTemplate":
            case "wrapItemText":
            case "useItemTextAsTitle":
                this._setListOption(name, value);
                break;
            case "dropDownContentTemplate":
                this._renderContent();
                break;
            case "selectedItemKey":
                this._selectedItemKeyChanged(value);
                break;
            case "selectedItem":
                break;
            case "onItemClick":
                this._createItemClickAction();
                break;
            case "onButtonClick":
                this._createActionClickAction();
                break;
            case "onSelectionChanged":
                this._createSelectionChangedAction();
                break;
            case "deferRendering":
                this.toggle(this.option("opened"));
                break;
            case "tabIndex":
                this._updateButtonGroup(name, value);
                break;
            default:
                this.callBase(args)
        }
    }
}).include(_data_helper.default);
(0, _component_registrator.default)("dxDropDownButton", DropDownButton);
var _default = DropDownButton;
exports.default = _default;
module.exports = exports.default;
module.exports.default = exports.default;
