"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.menuInjectionKey = void 0;
const vue_1 = require("vue");
const treemate_1 = require("treemate");
const vooks_1 = require("vooks");
const _mixins_1 = require("../../_mixins");
const _utils_1 = require("../../_utils");
const utils_1 = require("./utils");
const styles_1 = require("../styles");
const index_cssr_1 = require("./styles/index.cssr");
const interface_1 = require("../../layout/src/interface");
const menuProps = Object.assign(Object.assign({}, _mixins_1.useTheme.props), { options: {
        type: Array,
        default: () => []
    }, items: {
        type: Array,
        validator: () => {
            if (process.env.NODE_ENV !== 'production') {
                _utils_1.warn('menu', '`items` is deprecated, please use `options` instead.');
            }
            return true;
        },
        default: undefined
    }, collapsed: {
        type: Boolean,
        default: undefined
    }, collapsedWidth: {
        type: Number,
        default: 48
    }, iconSize: {
        type: Number,
        default: 20
    }, collapsedIconSize: {
        type: Number,
        default: 24
    }, rootIndent: Number, indent: {
        type: Number,
        default: 32
    }, defaultExpandAll: Boolean, defaultExpandedKeys: Array, expandedKeys: {
        type: Array,
        default: undefined
    }, value: [String, Number], defaultValue: {
        type: [String, Number],
        default: null
    }, mode: {
        type: String,
        default: 'vertical'
    }, disabled: Boolean, inverted: Boolean, 'onUpdate:expandedKeys': [Function, Array], onUpdateExpandedKeys: [Function, Array], onUpdateValue: [Function, Array], 'onUpdate:value': [Function, Array], 
    // deprecated
    onOpenNamesChange: {
        type: [Function, Array],
        validator: () => {
            _utils_1.warn('menu', '`on-open-names-change` is deprecated, please use `on-update:expanded-keys` instead.');
            return true;
        },
        default: undefined
    }, onSelect: {
        type: [Function, Array],
        validator: () => {
            _utils_1.warn('menu', '`on-select` is deprecated, please use `on-update:value` instead.');
            return true;
        },
        default: undefined
    }, onExpandedNamesChange: {
        type: [Function, Array],
        validator: () => {
            _utils_1.warn('menu', '`on-expanded-names-change` is deprecated, please use `on-update:expanded-keys` instead.');
            return true;
        },
        default: undefined
    }, expandIcon: Function, expandedNames: {
        type: Array,
        validator: () => {
            _utils_1.warn('menu', '`expanded-names` is deprecated, please use `expanded-keys` instead.');
            return true;
        },
        default: undefined
    }, defaultExpandedNames: {
        type: Array,
        validator: () => {
            _utils_1.warn('menu', '`default-expanded-names` is deprecated, please use `default-expanded-keys` instead.');
            return true;
        },
        default: undefined
    }, renderIcon: Function, renderLabel: Function, dropdownPlacement: {
        type: String,
        default: 'bottom'
    } });
exports.menuInjectionKey = Symbol('menu');
exports.default = vue_1.defineComponent({
    name: 'Menu',
    props: menuProps,
    setup(props) {
        const { mergedClsPrefixRef } = _mixins_1.useConfig(props);
        const themeRef = _mixins_1.useTheme('Menu', 'Menu', index_cssr_1.default, styles_1.menuLight, props, mergedClsPrefixRef);
        const layoutSider = vue_1.inject(interface_1.layoutSiderInjectionKey, null);
        const mergedCollapsedRef = vue_1.computed(() => {
            var _a;
            const { collapsed } = props;
            if (collapsed !== undefined)
                return collapsed;
            if (layoutSider) {
                const { collapseModeRef, collapsedRef } = layoutSider;
                if (collapseModeRef.value === 'width') {
                    return (_a = collapsedRef.value) !== null && _a !== void 0 ? _a : false;
                }
            }
            return false;
        });
        const treeMateRef = vue_1.computed(() => treemate_1.createTreeMate(props.items || props.options, {
            getKey(node) {
                var _a;
                return (_a = node.key) !== null && _a !== void 0 ? _a : node.name;
            }
        }));
        const uncontrolledValueRef = vue_1.ref(props.defaultValue);
        const controlledValueRef = vue_1.toRef(props, 'value');
        const mergedValueRef = vooks_1.useMergedState(controlledValueRef, uncontrolledValueRef);
        const uncontrolledExpandedKeysRef = vue_1.ref(props.defaultExpandAll
            ? treeMateRef.value.getNonLeafKeys()
            : props.defaultExpandedNames ||
                props.defaultExpandedKeys ||
                treeMateRef.value.getPath(mergedValueRef.value, {
                    includeSelf: false
                }).keyPath);
        const controlledExpandedKeysRef = vooks_1.useCompitable(props, [
            'expandedNames',
            'expandedKeys'
        ]);
        const mergedExpandedKeysRef = vooks_1.useMergedState(controlledExpandedKeysRef, uncontrolledExpandedKeysRef);
        const tmNodesRef = vue_1.computed(() => treeMateRef.value.treeNodes);
        const activePathRef = vue_1.computed(() => {
            return treeMateRef.value.getPath(mergedValueRef.value).keyPath;
        });
        vue_1.provide(exports.menuInjectionKey, {
            props,
            mergedCollapsedRef,
            mergedThemeRef: themeRef,
            mergedValueRef,
            mergedExpandedKeysRef,
            activePathRef,
            mergedClsPrefixRef,
            isHorizontalRef: vue_1.computed(() => props.mode === 'horizontal'),
            invertedRef: vue_1.toRef(props, 'inverted'),
            doSelect,
            toggleExpand
        });
        function doSelect(value, item) {
            const { 'onUpdate:value': _onUpdateValue, onUpdateValue, onSelect } = props;
            if (onUpdateValue) {
                _utils_1.call(onUpdateValue, value, item);
            }
            if (_onUpdateValue) {
                _utils_1.call(_onUpdateValue, value, item);
            }
            if (onSelect) {
                _utils_1.call(onSelect, value, item);
            }
            uncontrolledValueRef.value = value;
        }
        function doUpdateExpandedKeys(value) {
            const { 'onUpdate:expandedKeys': _onUpdateExpandedKeys, onUpdateExpandedKeys, onExpandedNamesChange, onOpenNamesChange } = props;
            if (_onUpdateExpandedKeys) {
                _utils_1.call(_onUpdateExpandedKeys, value);
            }
            if (onUpdateExpandedKeys) {
                _utils_1.call(onUpdateExpandedKeys, value);
            }
            // deprecated
            if (onExpandedNamesChange) {
                _utils_1.call(onExpandedNamesChange, value);
            }
            if (onOpenNamesChange) {
                _utils_1.call(onOpenNamesChange, value);
            }
            uncontrolledExpandedKeysRef.value = value;
        }
        function toggleExpand(key) {
            const currentExpandedKeys = Array.from(mergedExpandedKeysRef.value);
            const index = currentExpandedKeys.findIndex((expanededKey) => expanededKey === key);
            if (~index) {
                currentExpandedKeys.splice(index, 1);
            }
            else {
                currentExpandedKeys.push(key);
            }
            doUpdateExpandedKeys(currentExpandedKeys);
        }
        return {
            mergedClsPrefix: mergedClsPrefixRef,
            controlledExpandedKeys: controlledExpandedKeysRef,
            uncontrolledExpanededKeys: uncontrolledExpandedKeysRef,
            mergedExpandedKeys: mergedExpandedKeysRef,
            uncontrolledValue: uncontrolledValueRef,
            mergedValue: mergedValueRef,
            activePath: activePathRef,
            tmNodes: tmNodesRef,
            mergedTheme: themeRef,
            mergedCollapsed: mergedCollapsedRef,
            cssVars: vue_1.computed(() => {
                const { inverted } = props;
                const { common: { cubicBezierEaseInOut }, self } = themeRef.value;
                const { borderRadius, borderColorHorizontal, fontSize } = self;
                const vars = {
                    '--bezier': cubicBezierEaseInOut,
                    '--font-size': fontSize,
                    '--border-color-horizontal': borderColorHorizontal,
                    '--border-radius': borderRadius
                };
                if (inverted) {
                    vars['--group-text-color'] = self.groupTextColorInverted;
                    vars['--color'] = self.colorInverted;
                    vars['--item-text-color'] = self.itemTextColorInverted;
                    vars['--arrow-color'] = self.arrowColorInverted;
                    vars['--arrow-color-hover'] = self.arrowColorHoverInverted;
                    vars['--arrow-color-active'] = self.arrowColorActiveInverted;
                    vars['--arrow-color-child-active'] =
                        self.arrowColorChildActiveInverted;
                    vars['--item-icon-color'] = self.itemIconColorInverted;
                    vars['--item-text-color-hover'] = self.itemTextColorHoverInverted;
                    vars['--item-icon-color-hover'] = self.itemIconColorHoverInverted;
                    vars['--item-text-color-active'] = self.itemTextColorActiveInverted;
                    vars['--item-icon-color-active'] = self.itemIconColorActiveInverted;
                    vars['--item-icon-color-collapsed'] =
                        self.itemIconColorCollapsedInverted;
                    vars['--item-color-active'] = self.itemColorActiveInverted;
                    vars['--item-color-active-collapsed'] =
                        self.itemColorActiveCollapsedInverted;
                    vars['--item-text-color-child-active'] =
                        self.itemTextColorChildActiveInverted;
                    vars['--item-icon-color-child-active'] =
                        self.itemIconColorChildActiveInverted;
                }
                else {
                    vars['--group-text-color'] = self.groupTextColor;
                    vars['--color'] = self.color;
                    vars['--item-text-color'] = self.itemTextColor;
                    vars['--arrow-color'] = self.arrowColor;
                    vars['--arrow-color-hover'] = self.arrowColorHover;
                    vars['--arrow-color-active'] = self.arrowColorActive;
                    vars['--arrow-color-child-active'] = self.arrowColorChildActive;
                    vars['--item-icon-color'] = self.itemIconColor;
                    vars['--item-text-color-hover'] = self.itemTextColorHover;
                    vars['--item-icon-color-hover'] = self.itemIconColorHover;
                    vars['--item-text-color-active'] = self.itemTextColorActive;
                    vars['--item-icon-color-active'] = self.itemIconColorActive;
                    vars['--item-icon-color-collapsed'] = self.itemIconColorCollapsed;
                    vars['--item-color-active'] = self.itemColorActive;
                    vars['--item-color-active-collapsed'] = self.itemColorActiveCollapsed;
                    vars['--item-text-color-child-active'] = self.itemTextColorChildActive;
                    vars['--item-icon-color-child-active'] = self.itemIconColorChildActive;
                }
                return vars;
            })
        };
    },
    render() {
        const { mergedClsPrefix, mode } = this;
        return (vue_1.h("div", { role: mode === 'horizontal' ? 'menubar' : 'menu', class: [
                `${mergedClsPrefix}-menu`,
                `${mergedClsPrefix}-menu--${mode}`,
                this.mergedCollapsed && `${mergedClsPrefix}-menu--collapsed`
            ], style: this.cssVars }, this.tmNodes.map((tmNode) => utils_1.itemRenderer(tmNode))));
    }
});
