UNPKG

ant-design-vue

Version:

An enterprise-class UI design language and Vue-based implementation

418 lines (367 loc) 13.5 kB
import { createVNode as _createVNode, isVNode as _isVNode } from "vue"; function _extends() { _extends = Object.assign || 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); } import { Comment, inject } from 'vue'; import PropTypes from '../_util/vue-types'; import BaseMixin from '../_util/BaseMixin'; import KeyCode from '../_util/KeyCode'; import classNames from '../_util/classNames'; import { getKeyFromChildrenIndex, noop, isMobileDevice, menuAllProps } from './util'; import DOMWrap from './DOMWrap'; import { initDefaultProps, getOptionProps, getComponent, splitAttrs, getSlot } from '../_util/props-util'; import FunctionProvider from './FunctionProvider'; // import { getActiveKey } from '../vc-tabs/src/utils'; function _isSlot(s) { return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !_isVNode(s); } function allDisabled(arr) { if (!arr.length) { return true; } return arr.every(function (c) { return !!c.disabled; }); } function updateActiveKey(store, menuId, activeKey) { store.activeKey[menuId] = activeKey; } function getEventKey(props) { // when eventKey not available ,it's menu and return menu id '0-menu-' return props.eventKey || '0-menu-'; } export function saveRef(key, c) { if (c) { var index = this.instanceArrayKeyIndexMap[key]; this.instanceArray[index] = c; } } // export function getActiveKey(props, originalActiveKey) { // let activeKey = originalActiveKey; // const { eventKey, defaultActiveFirst, children } = props; // if (activeKey !== undefined && activeKey !== null) { // let found; // loopMenuItem(children, (c, i) => { // const propsData = getPropsData(c); // if (c && !propsData.disabled && activeKey === getKeyFromChildrenIndex(c, eventKey, i)) { // found = true; // } // }); // if (found) { // return activeKey; // } // } // activeKey = null; // if (defaultActiveFirst) { // loopMenuItem(children, (c, i) => { // const propsData = getPropsData(c); // const noActiveKey = activeKey === null || activeKey === undefined; // if (noActiveKey && c && !propsData.disabled) { // activeKey = getKeyFromChildrenIndex(c, eventKey, i); // } // }); // return activeKey; // } // return activeKey; // } var SubPopupMenu = { name: 'SubPopupMenu', inheritAttrs: false, props: initDefaultProps({ // onSelect: PropTypes.func, // onClick: PropTypes.func, // onDeselect: PropTypes.func, // onOpenChange: PropTypes.func, // onDestroy: PropTypes.func, prefixCls: PropTypes.string, openTransitionName: PropTypes.string, openAnimation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), openKeys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])), visible: PropTypes.looseBool, eventKey: PropTypes.string, // adding in refactor focusable: PropTypes.looseBool, multiple: PropTypes.looseBool, defaultActiveFirst: PropTypes.looseBool, activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), defaultSelectedKeys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])), defaultOpenKeys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])), level: PropTypes.number, mode: PropTypes.oneOf(['horizontal', 'vertical', 'vertical-left', 'vertical-right', 'inline']), triggerSubMenuAction: PropTypes.oneOf(['click', 'hover']), inlineIndent: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), manualRef: PropTypes.func, itemIcon: PropTypes.any, expandIcon: PropTypes.any, overflowedIndicator: PropTypes.any, children: PropTypes.any.def([]), subMenuOpenDelay: PropTypes.number.def(0.1), subMenuCloseDelay: PropTypes.number.def(0.1), forceSubMenuRender: PropTypes.looseBool.def(false), parentUniKeys: PropTypes.array.def(function () { return []; }), parentUniKey: PropTypes.string, theme: PropTypes.string }, { prefixCls: 'rc-menu', mode: 'vertical', level: 1, inlineIndent: 24, visible: true, focusable: true, manualRef: noop }), mixins: [BaseMixin], setup: function setup() { var store = inject('menuStore', function () { return {}; }); return { store: store }; }, created: function created() { var props = getOptionProps(this); this.prevProps = _extends({}, props); this.store.activeKey[props.eventKey] = this.store.getActiveKey(props.activeKey); this.instanceArray = []; }, mounted: function mounted() { // invoke customized ref to expose component to mixin if (this.manualRef) { this.manualRef(this); } }, updated: function updated() { var props = getOptionProps(this); var prevProps = this.prevProps; var originalActiveKey = 'activeKey' in props ? props.activeKey : this.store.activeKey[getEventKey(props)]; var activeKey = this.store.getActiveKey(originalActiveKey); if (activeKey !== originalActiveKey) { updateActiveKey(this.store, getEventKey(props), activeKey); } else if ('activeKey' in prevProps) { // If prev activeKey is not same as current activeKey, // we should set it. var prevActiveKey = this.store.getActiveKey(prevProps.activeKey); if (activeKey !== prevActiveKey) { updateActiveKey(this.store, getEventKey(props), activeKey); } } this.prevProps = _extends({}, props); }, methods: { // all keyboard events callbacks run from here at first onKeyDown: function onKeyDown(e, callback) { var keyCode = e.keyCode; var handled; this.getFlatInstanceArray().forEach(function (obj) { if (obj && obj.active && obj.onKeyDown) { handled = obj.onKeyDown(e); } }); if (handled) { return 1; } var activeItem = null; if (keyCode === KeyCode.UP || keyCode === KeyCode.DOWN) { activeItem = this.step(keyCode === KeyCode.UP ? -1 : 1); } if (activeItem) { e.preventDefault(); updateActiveKey(this.store, getEventKey(this.$props), activeItem.eventKey); if (typeof callback === 'function') { callback(activeItem); } return 1; } return undefined; }, onItemHover: function onItemHover(e) { var key = e.key, hover = e.hover; updateActiveKey(this.store, getEventKey(this.$props), hover ? key : null); }, onDeselect: function onDeselect(selectInfo) { this.__emit('deselect', selectInfo); }, onSelect: function onSelect(selectInfo) { this.__emit('select', selectInfo); }, onClick: function onClick(e) { this.__emit('click', e); }, onOpenChange: function onOpenChange(e) { this.__emit('openChange', e); }, onDestroy: function onDestroy(key) { this.__emit('destroy', key); }, getFlatInstanceArray: function getFlatInstanceArray() { return this.instanceArray; }, getOpenTransitionName: function getOpenTransitionName() { return this.$props.openTransitionName; }, step: function step(direction) { var children = this.getFlatInstanceArray(); var activeKey = this.store.activeKey[getEventKey(this.$props)]; var len = children.length; if (!len) { return null; } if (direction < 0) { children = children.concat().reverse(); } // find current activeIndex var activeIndex = -1; children.every(function (c, ci) { if (c && c.eventKey === activeKey) { activeIndex = ci; return false; } return true; }); if (!this.defaultActiveFirst && activeIndex !== -1 && allDisabled(children.slice(activeIndex, len - 1))) { return undefined; } var start = (activeIndex + 1) % len; var i = start; do { var child = children[i]; if (!child || child.disabled) { i = (i + 1) % len; } else { return child; } } while (i !== start); return null; }, getIcon: function getIcon(instance, name) { return getComponent(instance, name); }, renderCommonMenuItem: function renderCommonMenuItem(child, i, extraProps) { var _this = this; if (child.type === Comment) { return child; } var state = this.store; var props = this.$props; var key = getKeyFromChildrenIndex(child, props.eventKey, i); var childProps = child.props || {}; // child.props 包含事件 var isActive = key === state.activeKey[getEventKey(this.$props)]; if (!childProps.disabled) { // manualRef的执行顺序不能保证,使用key映射ref在this.instanceArray中的位置 this.instanceArrayKeyIndexMap[key] = Object.keys(this.instanceArrayKeyIndexMap).length; } var newChildProps = _extends(_extends({ mode: childProps.mode || props.mode, level: props.level, inlineIndent: props.inlineIndent, renderMenuItem: this.renderMenuItem, rootPrefixCls: props.prefixCls, index: i, // customized ref function, need to be invoked manually in child's componentDidMount manualRef: childProps.disabled ? noop : saveRef.bind(this, key), eventKey: key, active: !childProps.disabled && isActive, multiple: props.multiple, openTransitionName: this.getOpenTransitionName(), openAnimation: props.openAnimation, subMenuOpenDelay: props.subMenuOpenDelay, subMenuCloseDelay: props.subMenuCloseDelay, builtinPlacements: props.builtinPlacements, itemIcon: this.getIcon(child, 'itemIcon') || this.getIcon(this, 'itemIcon'), expandIcon: this.getIcon(child, 'expandIcon') || this.getIcon(this, 'expandIcon') }, extraProps), { onClick: function onClick(e) { (childProps.onClick || noop)(e); _this.onClick(e); }, onItemHover: this.onItemHover, onOpenChange: this.onOpenChange, onDeselect: this.onDeselect, // destroy: this.onDestroy, onSelect: this.onSelect, parentUniKeys: this.parentUniKeys, parentUniKey: this.parentUniKey }); if (props.forceSubMenuRender !== undefined) { newChildProps.forceSubMenuRender = props.forceSubMenuRender; } // ref: https://github.com/ant-design/ant-design/issues/13943 if (props.mode === 'inline' || isMobileDevice()) { newChildProps.triggerSubMenuAction = 'click'; } return _createVNode(FunctionProvider, { "extraProps": newChildProps }, _isSlot(child) ? child : { default: function _default() { return [child]; } }); }, renderMenuItem: function renderMenuItem(c, i, subMenuKey) { if (!c) { return null; } var state = this.store; var extraProps = { openKeys: state.openKeys, selectedKeys: state.selectedKeys, triggerSubMenuAction: this.triggerSubMenuAction, isRootMenu: false, subMenuKey: subMenuKey }; return this.renderCommonMenuItem(c, i, extraProps); } }, render: function render() { var _slot; var _this2 = this; var props = _extends({}, this.$props); var _splitAttrs = splitAttrs(this.$attrs), onEvents = _splitAttrs.onEvents, extraAttrs = _splitAttrs.extraAttrs; var eventKey = props.eventKey, prefixCls = props.prefixCls, visible = props.visible, level = props.level, mode = props.mode, theme = props.theme; this.instanceArray = []; this.instanceArrayKeyIndexMap = {}; var className = classNames(extraAttrs.class, props.prefixCls, "".concat(props.prefixCls, "-").concat(props.mode)); menuAllProps.forEach(function (key) { return delete props[key]; }); // Otherwise, the propagated click event will trigger another onClick delete onEvents.onClick; var domWrapProps = _extends(_extends(_extends({}, props), { tag: 'ul', // hiddenClassName: `${prefixCls}-hidden`, visible: visible, prefixCls: prefixCls, level: level, mode: mode, theme: theme, overflowedIndicator: getComponent(this, 'overflowedIndicator'), role: props.role || 'menu', class: className, style: extraAttrs.style }), onEvents); if (extraAttrs.id !== undefined) { domWrapProps.id = extraAttrs.id; } if (props.focusable) { domWrapProps.tabindex = '0'; domWrapProps.onKeydown = this.onKeyDown; } delete domWrapProps.children; return (// ESLint is not smart enough to know that the type of `children` was checked. /* eslint-disable */ _createVNode(DOMWrap, domWrapProps, _isSlot(_slot = getSlot(this).map(function (c, i) { return _this2.renderMenuItem(c, i, eventKey || '0-menu-'); })) ? _slot : { default: function _default() { return [_slot]; } }) /*eslint -enable */ ); } }; export default SubPopupMenu;