@aplus-frontend/antdv
Version:
Vue basic component library maintained based on ant-design-vue
490 lines (489 loc) • 19.2 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.menuProps = exports.default = void 0;
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var _vue = require("vue");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _shallowequal = _interopRequireDefault(require("../../_util/shallowequal"));
var _useMenuContext = _interopRequireWildcard(require("./hooks/useMenuContext"));
var _useConfigInject = _interopRequireDefault(require("../../config-provider/hooks/useConfigInject"));
var _devWarning = _interopRequireDefault(require("../../vc-util/devWarning"));
var _uniq = _interopRequireDefault(require("lodash/uniq"));
var _injectionKey = require("../../layout/injectionKey");
var _propsUtil = require("../../_util/props-util");
var _vcOverflow = _interopRequireDefault(require("../../vc-overflow"));
var _MenuItem = _interopRequireDefault(require("./MenuItem"));
var _SubMenu = _interopRequireDefault(require("./SubMenu"));
var _EllipsisOutlined = _interopRequireDefault(require("@ant-design/icons-vue/lib/icons/EllipsisOutlined"));
var _vnode = require("../../_util/vnode");
var _useKeyPath = require("./hooks/useKeyPath");
var _collapseMotion = _interopRequireDefault(require("../../_util/collapseMotion"));
var _useItems = _interopRequireDefault(require("./hooks/useItems"));
var _style = _interopRequireDefault(require("../style"));
var _OverrideContext = require("./OverrideContext");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const menuProps = () => ({
id: String,
prefixCls: String,
// donot use items, now only support inner use
items: Array,
disabled: Boolean,
inlineCollapsed: Boolean,
disabledOverflow: Boolean,
forceSubMenuRender: Boolean,
openKeys: Array,
selectedKeys: Array,
activeKey: String,
selectable: {
type: Boolean,
default: true
},
multiple: {
type: Boolean,
default: false
},
tabindex: {
type: [Number, String]
},
motion: Object,
role: String,
theme: {
type: String,
default: 'light'
},
mode: {
type: String,
default: 'vertical'
},
inlineIndent: {
type: Number,
default: 24
},
subMenuOpenDelay: {
type: Number,
default: 0
},
subMenuCloseDelay: {
type: Number,
default: 0.1
},
builtinPlacements: {
type: Object
},
triggerSubMenuAction: {
type: String,
default: 'hover'
},
getPopupContainer: Function,
expandIcon: Function,
onOpenChange: Function,
onSelect: Function,
onDeselect: Function,
onClick: [Function, Array],
onFocus: Function,
onBlur: Function,
onMousedown: Function,
'onUpdate:openKeys': Function,
'onUpdate:selectedKeys': Function,
'onUpdate:activeKey': Function
});
exports.menuProps = menuProps;
const EMPTY_LIST = [];
var _default = exports.default = (0, _vue.defineComponent)({
compatConfig: {
MODE: 3
},
name: 'AMenu',
inheritAttrs: false,
props: menuProps(),
slots: Object,
setup(props, _ref) {
let {
slots,
emit,
attrs
} = _ref;
const {
direction,
getPrefixCls
} = (0, _useConfigInject.default)('menu', props);
const override = (0, _OverrideContext.useInjectOverride)();
const prefixCls = (0, _vue.computed)(() => {
var _a;
return getPrefixCls('menu', props.prefixCls || ((_a = override === null || override === void 0 ? void 0 : override.prefixCls) === null || _a === void 0 ? void 0 : _a.value));
});
const [wrapSSR, hashId] = (0, _style.default)(prefixCls, (0, _vue.computed)(() => {
return !override;
}));
const store = (0, _vue.shallowRef)(new Map());
const siderCollapsed = (0, _vue.inject)(_injectionKey.SiderCollapsedKey, (0, _vue.ref)(undefined));
const inlineCollapsed = (0, _vue.computed)(() => {
if (siderCollapsed.value !== undefined) {
return siderCollapsed.value;
}
return props.inlineCollapsed;
});
const {
itemsNodes
} = (0, _useItems.default)(props);
const isMounted = (0, _vue.shallowRef)(false);
(0, _vue.onMounted)(() => {
isMounted.value = true;
});
(0, _vue.watchEffect)(() => {
(0, _devWarning.default)(!(props.inlineCollapsed === true && props.mode !== 'inline'), 'Menu', '`inlineCollapsed` should only be used when `mode` is inline.');
(0, _devWarning.default)(!(siderCollapsed.value !== undefined && props.inlineCollapsed === true), 'Menu', '`inlineCollapsed` not control Menu under Sider. Should set `collapsed` on Sider instead.');
// devWarning(
// !!props.items && !slots.default,
// 'Menu',
// '`children` will be removed in next major version. Please use `items` instead.',
// );
});
const activeKeys = (0, _vue.ref)([]);
const mergedSelectedKeys = (0, _vue.ref)([]);
const keyMapStore = (0, _vue.ref)({});
(0, _vue.watch)(store, () => {
const newKeyMapStore = {};
for (const menuInfo of store.value.values()) {
newKeyMapStore[menuInfo.key] = menuInfo;
}
keyMapStore.value = newKeyMapStore;
}, {
flush: 'post'
});
(0, _vue.watchEffect)(() => {
if (props.activeKey !== undefined) {
let keys = [];
const menuInfo = props.activeKey ? keyMapStore.value[props.activeKey] : undefined;
if (menuInfo && props.activeKey !== undefined) {
keys = (0, _uniq.default)([].concat((0, _vue.unref)(menuInfo.parentKeys), props.activeKey));
} else {
keys = [];
}
if (!(0, _shallowequal.default)(activeKeys.value, keys)) {
activeKeys.value = keys;
}
}
});
(0, _vue.watch)(() => props.selectedKeys, selectedKeys => {
if (selectedKeys) {
mergedSelectedKeys.value = selectedKeys.slice();
}
}, {
immediate: true,
deep: true
});
const selectedSubMenuKeys = (0, _vue.ref)([]);
(0, _vue.watch)([keyMapStore, mergedSelectedKeys], () => {
let subMenuParentKeys = [];
mergedSelectedKeys.value.forEach(key => {
const menuInfo = keyMapStore.value[key];
if (menuInfo) {
subMenuParentKeys = subMenuParentKeys.concat((0, _vue.unref)(menuInfo.parentKeys));
}
});
subMenuParentKeys = (0, _uniq.default)(subMenuParentKeys);
if (!(0, _shallowequal.default)(selectedSubMenuKeys.value, subMenuParentKeys)) {
selectedSubMenuKeys.value = subMenuParentKeys;
}
}, {
immediate: true
});
// >>>>> Trigger select
const triggerSelection = info => {
if (props.selectable) {
// Insert or Remove
const {
key: targetKey
} = info;
const exist = mergedSelectedKeys.value.includes(targetKey);
let newSelectedKeys;
if (props.multiple) {
if (exist) {
newSelectedKeys = mergedSelectedKeys.value.filter(key => key !== targetKey);
} else {
newSelectedKeys = [...mergedSelectedKeys.value, targetKey];
}
} else {
newSelectedKeys = [targetKey];
}
// Trigger event
const selectInfo = (0, _extends2.default)((0, _extends2.default)({}, info), {
selectedKeys: newSelectedKeys
});
if (!(0, _shallowequal.default)(newSelectedKeys, mergedSelectedKeys.value)) {
if (props.selectedKeys === undefined) {
mergedSelectedKeys.value = newSelectedKeys;
}
emit('update:selectedKeys', newSelectedKeys);
if (exist && props.multiple) {
emit('deselect', selectInfo);
} else {
emit('select', selectInfo);
}
}
}
// Whatever selectable, always close it
if (mergedMode.value !== 'inline' && !props.multiple && mergedOpenKeys.value.length) {
triggerOpenKeys(EMPTY_LIST);
}
};
const mergedOpenKeys = (0, _vue.ref)([]);
(0, _vue.watch)(() => props.openKeys, function () {
let openKeys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : mergedOpenKeys.value;
if (!(0, _shallowequal.default)(mergedOpenKeys.value, openKeys)) {
mergedOpenKeys.value = openKeys.slice();
}
}, {
immediate: true,
deep: true
});
let timeout;
const changeActiveKeys = keys => {
clearTimeout(timeout);
timeout = setTimeout(() => {
if (props.activeKey === undefined) {
activeKeys.value = keys;
}
emit('update:activeKey', keys[keys.length - 1]);
});
};
const disabled = (0, _vue.computed)(() => !!props.disabled);
const isRtl = (0, _vue.computed)(() => direction.value === 'rtl');
const mergedMode = (0, _vue.ref)('vertical');
const mergedInlineCollapsed = (0, _vue.shallowRef)(false);
(0, _vue.watchEffect)(() => {
var _a;
if ((props.mode === 'inline' || props.mode === 'vertical') && inlineCollapsed.value) {
mergedMode.value = 'vertical';
mergedInlineCollapsed.value = inlineCollapsed.value;
} else {
mergedMode.value = props.mode;
mergedInlineCollapsed.value = false;
}
if ((_a = override === null || override === void 0 ? void 0 : override.mode) === null || _a === void 0 ? void 0 : _a.value) {
mergedMode.value = override.mode.value;
}
});
const isInlineMode = (0, _vue.computed)(() => mergedMode.value === 'inline');
const triggerOpenKeys = keys => {
mergedOpenKeys.value = keys;
emit('update:openKeys', keys);
emit('openChange', keys);
};
// >>>>> Cache & Reset open keys when inlineCollapsed changed
const inlineCacheOpenKeys = (0, _vue.ref)(mergedOpenKeys.value);
const mountRef = (0, _vue.shallowRef)(false);
// Cache
(0, _vue.watch)(mergedOpenKeys, () => {
if (isInlineMode.value) {
inlineCacheOpenKeys.value = mergedOpenKeys.value;
}
}, {
immediate: true
});
// Restore
(0, _vue.watch)(isInlineMode, () => {
if (!mountRef.value) {
mountRef.value = true;
return;
}
if (isInlineMode.value) {
mergedOpenKeys.value = inlineCacheOpenKeys.value;
} else {
// Trigger open event in case its in control
triggerOpenKeys(EMPTY_LIST);
}
}, {
immediate: true
});
const className = (0, _vue.computed)(() => {
return {
[`${prefixCls.value}`]: true,
[`${prefixCls.value}-root`]: true,
[`${prefixCls.value}-${mergedMode.value}`]: true,
[`${prefixCls.value}-inline-collapsed`]: mergedInlineCollapsed.value,
[`${prefixCls.value}-rtl`]: isRtl.value,
[`${prefixCls.value}-${props.theme}`]: true
};
});
const rootPrefixCls = (0, _vue.computed)(() => getPrefixCls());
const defaultMotions = (0, _vue.computed)(() => ({
horizontal: {
name: `${rootPrefixCls.value}-slide-up`
},
inline: (0, _collapseMotion.default)(`${rootPrefixCls.value}-motion-collapse`),
other: {
name: `${rootPrefixCls.value}-zoom-big`
}
}));
(0, _useMenuContext.useProvideFirstLevel)(true);
const getChildrenKeys = function () {
let eventKeys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
const keys = [];
const storeValue = store.value;
eventKeys.forEach(eventKey => {
const {
key,
childrenEventKeys
} = storeValue.get(eventKey);
keys.push(key, ...getChildrenKeys((0, _vue.unref)(childrenEventKeys)));
});
return keys;
};
// ========================= Open =========================
/**
* Click for item. SubMenu do not have selection status
*/
const onInternalClick = info => {
var _a;
emit('click', info);
triggerSelection(info);
(_a = override === null || override === void 0 ? void 0 : override.onClick) === null || _a === void 0 ? void 0 : _a.call(override);
};
const onInternalOpenChange = (key, open) => {
var _a;
const childrenEventKeys = ((_a = keyMapStore.value[key]) === null || _a === void 0 ? void 0 : _a.childrenEventKeys) || [];
let newOpenKeys = mergedOpenKeys.value.filter(k => k !== key);
if (open) {
newOpenKeys.push(key);
} else if (mergedMode.value !== 'inline') {
// We need find all related popup to close
const subPathKeys = getChildrenKeys((0, _vue.unref)(childrenEventKeys));
newOpenKeys = (0, _uniq.default)(newOpenKeys.filter(k => !subPathKeys.includes(k)));
}
if (!(0, _shallowequal.default)(mergedOpenKeys, newOpenKeys)) {
triggerOpenKeys(newOpenKeys);
}
};
const registerMenuInfo = (key, info) => {
store.value.set(key, info);
store.value = new Map(store.value);
};
const unRegisterMenuInfo = key => {
store.value.delete(key);
store.value = new Map(store.value);
};
const lastVisibleIndex = (0, _vue.ref)(0);
const expandIcon = (0, _vue.computed)(() => {
var _a;
return props.expandIcon || slots.expandIcon || ((_a = override === null || override === void 0 ? void 0 : override.expandIcon) === null || _a === void 0 ? void 0 : _a.value) ? opt => {
let icon = props.expandIcon || slots.expandIcon;
icon = typeof icon === 'function' ? icon(opt) : icon;
return (0, _vnode.cloneElement)(icon, {
class: `${prefixCls.value}-submenu-expand-icon`
}, false);
} : null;
});
(0, _useMenuContext.default)({
prefixCls,
activeKeys,
openKeys: mergedOpenKeys,
selectedKeys: mergedSelectedKeys,
changeActiveKeys,
disabled,
rtl: isRtl,
mode: mergedMode,
inlineIndent: (0, _vue.computed)(() => props.inlineIndent),
subMenuCloseDelay: (0, _vue.computed)(() => props.subMenuCloseDelay),
subMenuOpenDelay: (0, _vue.computed)(() => props.subMenuOpenDelay),
builtinPlacements: (0, _vue.computed)(() => props.builtinPlacements),
triggerSubMenuAction: (0, _vue.computed)(() => props.triggerSubMenuAction),
getPopupContainer: (0, _vue.computed)(() => props.getPopupContainer),
inlineCollapsed: mergedInlineCollapsed,
theme: (0, _vue.computed)(() => props.theme),
siderCollapsed,
defaultMotions: (0, _vue.computed)(() => isMounted.value ? defaultMotions.value : null),
motion: (0, _vue.computed)(() => isMounted.value ? props.motion : null),
overflowDisabled: (0, _vue.shallowRef)(undefined),
onOpenChange: onInternalOpenChange,
onItemClick: onInternalClick,
registerMenuInfo,
unRegisterMenuInfo,
selectedSubMenuKeys,
expandIcon,
forceSubMenuRender: (0, _vue.computed)(() => props.forceSubMenuRender),
rootClassName: hashId
});
const getChildrenList = () => {
var _a;
return itemsNodes.value || (0, _propsUtil.flattenChildren)((_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
};
return () => {
var _a;
const childList = getChildrenList();
const allVisible = lastVisibleIndex.value >= childList.length - 1 || mergedMode.value !== 'horizontal' || props.disabledOverflow;
// >>>>> Children
const getWrapperList = childList => {
return mergedMode.value !== 'horizontal' || props.disabledOverflow ? childList :
// Need wrap for overflow dropdown that do not response for open
childList.map((child, index) => // Always wrap provider to avoid sub node re-mount
(0, _vue.createVNode)(_useMenuContext.MenuContextProvider, {
"key": child.key,
"overflowDisabled": index > lastVisibleIndex.value
}, {
default: () => child
}));
};
const overflowedIndicator = ((_a = slots.overflowedIndicator) === null || _a === void 0 ? void 0 : _a.call(slots)) || (0, _vue.createVNode)(_EllipsisOutlined.default, null, null);
return wrapSSR((0, _vue.createVNode)(_vcOverflow.default, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, attrs), {}, {
"onMousedown": props.onMousedown,
"prefixCls": `${prefixCls.value}-overflow`,
"component": "ul",
"itemComponent": _MenuItem.default,
"class": [className.value, attrs.class, hashId.value],
"role": "menu",
"id": props.id,
"data": getWrapperList(childList),
"renderRawItem": node => node,
"renderRawRest": omitItems => {
// We use origin list since wrapped list use context to prevent open
const len = omitItems.length;
const originOmitItems = len ? childList.slice(-len) : null;
return (0, _vue.createVNode)(_vue.Fragment, null, [(0, _vue.createVNode)(_SubMenu.default, {
"eventKey": _useKeyPath.OVERFLOW_KEY,
"key": _useKeyPath.OVERFLOW_KEY,
"title": overflowedIndicator,
"disabled": allVisible,
"internalPopupClose": len === 0
}, {
default: () => originOmitItems
}), (0, _vue.createVNode)(_useKeyPath.PathContext, null, {
default: () => [(0, _vue.createVNode)(_SubMenu.default, {
"eventKey": _useKeyPath.OVERFLOW_KEY,
"key": _useKeyPath.OVERFLOW_KEY,
"title": overflowedIndicator,
"disabled": allVisible,
"internalPopupClose": len === 0
}, {
default: () => originOmitItems
})]
})]);
},
"maxCount": mergedMode.value !== 'horizontal' || props.disabledOverflow ? _vcOverflow.default.INVALIDATE : _vcOverflow.default.RESPONSIVE,
"ssr": "full",
"data-menu-list": true,
"onVisibleChange": newLastIndex => {
lastVisibleIndex.value = newLastIndex;
}
}), {
default: () => [(0, _vue.createVNode)(_vue.Teleport, {
"to": "body"
}, {
default: () => [(0, _vue.createVNode)("div", {
"style": {
display: 'none'
},
"aria-hidden": true
}, [(0, _vue.createVNode)(_useKeyPath.PathContext, null, {
default: () => [getWrapperList(getChildrenList())]
})])]
})]
}));
};
}
});
;