UNPKG

naive-ui

Version:

A Vue 3 Component Library. Fairly Complete, Theme Customizable, Uses TypeScript, Fast

486 lines (485 loc) 24.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.menuProps = void 0; const seemly_1 = require("seemly"); const treemate_1 = require("treemate"); const vooks_1 = require("vooks"); const vue_1 = require("vue"); const vueuc_1 = require("vueuc"); const _mixins_1 = require("../../_mixins"); const _utils_1 = require("../../_utils"); const interface_1 = require("../../layout/src/interface"); const styles_1 = require("../styles"); const context_1 = require("./context"); const index_cssr_1 = __importDefault(require("./styles/index.cssr")); const Submenu_1 = require("./Submenu"); const useCheckDeprecated_1 = require("./useCheckDeprecated"); const utils_1 = require("./utils"); exports.menuProps = Object.assign(Object.assign({}, _mixins_1.useTheme.props), { options: { type: Array, default: () => [] }, 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 }, labelField: { type: String, default: 'label' }, keyField: { type: String, default: 'key' }, childrenField: { type: String, default: 'children' }, disabledField: { type: String, default: 'disabled' }, defaultExpandAll: Boolean, defaultExpandedKeys: Array, expandedKeys: Array, value: [String, Number], defaultValue: { type: [String, Number], default: null }, mode: { type: String, default: 'vertical' }, watchProps: { type: Array, default: undefined }, disabled: Boolean, show: { type: Boolean, default: true }, inverted: Boolean, 'onUpdate:expandedKeys': [Function, Array], onUpdateExpandedKeys: [Function, Array], onUpdateValue: [Function, Array], 'onUpdate:value': [Function, Array], expandIcon: Function, renderIcon: Function, renderLabel: Function, renderExtra: Function, dropdownProps: Object, accordion: Boolean, nodeProps: Function, dropdownPlacement: { type: String, default: 'bottom' }, responsive: Boolean, // deprecated items: Array, onOpenNamesChange: [Function, Array], onSelect: [Function, Array], onExpandedNamesChange: [Function, Array], expandedNames: Array, defaultExpandedNames: Array }); exports.default = (0, vue_1.defineComponent)({ name: 'Menu', inheritAttrs: false, props: exports.menuProps, setup(props) { if (process.env.NODE_ENV !== 'production') { (0, useCheckDeprecated_1.useCheckDeprecated)(props); } const { mergedClsPrefixRef, inlineThemeDisabled } = (0, _mixins_1.useConfig)(props); const themeRef = (0, _mixins_1.useTheme)('Menu', '-menu', index_cssr_1.default, styles_1.menuLight, props, mergedClsPrefixRef); const layoutSider = (0, vue_1.inject)(interface_1.layoutSiderInjectionKey, null); const mergedCollapsedRef = (0, 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 = (0, vue_1.computed)(() => { const { keyField, childrenField, disabledField } = props; return (0, treemate_1.createTreeMate)(props.items || props.options, { getIgnored(node) { return (0, utils_1.isIgnoredNode)(node); }, getChildren(node) { return node[childrenField]; }, getDisabled(node) { return node[disabledField]; }, getKey(node) { var _a; return (_a = node[keyField]) !== null && _a !== void 0 ? _a : node.name; } }); }); const treeKeysLevelOneRef = (0, vue_1.computed)(() => new Set(treeMateRef.value.treeNodes.map(e => e.key))); const { watchProps } = props; const uncontrolledValueRef = (0, vue_1.ref)(null); if (watchProps === null || watchProps === void 0 ? void 0 : watchProps.includes('defaultValue')) { (0, vue_1.watchEffect)(() => { uncontrolledValueRef.value = props.defaultValue; }); } else { uncontrolledValueRef.value = props.defaultValue; } const controlledValueRef = (0, vue_1.toRef)(props, 'value'); const mergedValueRef = (0, vooks_1.useMergedState)(controlledValueRef, uncontrolledValueRef); const uncontrolledExpandedKeysRef = (0, vue_1.ref)([]); const initUncontrolledExpandedKeys = () => { uncontrolledExpandedKeysRef.value = props.defaultExpandAll ? treeMateRef.value.getNonLeafKeys() : props.defaultExpandedNames || props.defaultExpandedKeys || treeMateRef.value.getPath(mergedValueRef.value, { includeSelf: false }).keyPath; }; if (watchProps === null || watchProps === void 0 ? void 0 : watchProps.includes('defaultExpandedKeys')) { (0, vue_1.watchEffect)(initUncontrolledExpandedKeys); } else { initUncontrolledExpandedKeys(); } const controlledExpandedKeysRef = (0, vooks_1.useCompitable)(props, [ 'expandedNames', 'expandedKeys' ]); const mergedExpandedKeysRef = (0, vooks_1.useMergedState)(controlledExpandedKeysRef, uncontrolledExpandedKeysRef); const tmNodesRef = (0, vue_1.computed)(() => treeMateRef.value.treeNodes); const activePathRef = (0, vue_1.computed)(() => { return treeMateRef.value.getPath(mergedValueRef.value).keyPath; }); (0, vue_1.provide)(context_1.menuInjectionKey, { props, mergedCollapsedRef, mergedThemeRef: themeRef, mergedValueRef, mergedExpandedKeysRef, activePathRef, mergedClsPrefixRef, isHorizontalRef: (0, vue_1.computed)(() => props.mode === 'horizontal'), invertedRef: (0, vue_1.toRef)(props, 'inverted'), doSelect, toggleExpand }); function doSelect(value, item) { const { 'onUpdate:value': _onUpdateValue, onUpdateValue, onSelect } = props; if (onUpdateValue) { (0, _utils_1.call)(onUpdateValue, value, item); } if (_onUpdateValue) { (0, _utils_1.call)(_onUpdateValue, value, item); } if (onSelect) { (0, _utils_1.call)(onSelect, value, item); } uncontrolledValueRef.value = value; } function doUpdateExpandedKeys(value) { const { 'onUpdate:expandedKeys': _onUpdateExpandedKeys, onUpdateExpandedKeys, onExpandedNamesChange, onOpenNamesChange } = props; if (_onUpdateExpandedKeys) { (0, _utils_1.call)(_onUpdateExpandedKeys, value); } if (onUpdateExpandedKeys) { (0, _utils_1.call)(onUpdateExpandedKeys, value); } // deprecated if (onExpandedNamesChange) { (0, _utils_1.call)(onExpandedNamesChange, value); } if (onOpenNamesChange) { (0, _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 { if (props.accordion) { if (treeKeysLevelOneRef.value.has(key)) { const closeKeyIndex = currentExpandedKeys.findIndex(e => treeKeysLevelOneRef.value.has(e)); if (closeKeyIndex > -1) { currentExpandedKeys.splice(closeKeyIndex, 1); } } } currentExpandedKeys.push(key); } doUpdateExpandedKeys(currentExpandedKeys); } const showOption = (key) => { const selectedKeyPath = treeMateRef.value.getPath(key !== null && key !== void 0 ? key : mergedValueRef.value, { includeSelf: false }).keyPath; if (!selectedKeyPath.length) return; const currentExpandedKeys = Array.from(mergedExpandedKeysRef.value); const nextExpandedKeys = new Set([ ...currentExpandedKeys, ...selectedKeyPath ]); if (props.accordion) { treeKeysLevelOneRef.value.forEach((firstLevelKey) => { if (nextExpandedKeys.has(firstLevelKey) && !selectedKeyPath.includes(firstLevelKey)) { nextExpandedKeys.delete(firstLevelKey); } }); } doUpdateExpandedKeys(Array.from(nextExpandedKeys)); }; const cssVarsRef = (0, vue_1.computed)(() => { const { inverted } = props; const { common: { cubicBezierEaseInOut }, self } = themeRef.value; const { borderRadius, borderColorHorizontal, fontSize, itemHeight, dividerColor } = self; const vars = { '--n-divider-color': dividerColor, '--n-bezier': cubicBezierEaseInOut, '--n-font-size': fontSize, '--n-border-color-horizontal': borderColorHorizontal, '--n-border-radius': borderRadius, '--n-item-height': itemHeight }; if (inverted) { vars['--n-group-text-color'] = self.groupTextColorInverted; vars['--n-color'] = self.colorInverted; vars['--n-item-text-color'] = self.itemTextColorInverted; vars['--n-item-text-color-hover'] = self.itemTextColorHoverInverted; vars['--n-item-text-color-active'] = self.itemTextColorActiveInverted; vars['--n-item-text-color-child-active'] = self.itemTextColorChildActiveInverted; vars['--n-item-text-color-child-active-hover'] = self.itemTextColorChildActiveInverted; vars['--n-item-text-color-active-hover'] = self.itemTextColorActiveHoverInverted; vars['--n-item-icon-color'] = self.itemIconColorInverted; vars['--n-item-icon-color-hover'] = self.itemIconColorHoverInverted; vars['--n-item-icon-color-active'] = self.itemIconColorActiveInverted; vars['--n-item-icon-color-active-hover'] = self.itemIconColorActiveHoverInverted; vars['--n-item-icon-color-child-active'] = self.itemIconColorChildActiveInverted; vars['--n-item-icon-color-child-active-hover'] = self.itemIconColorChildActiveHoverInverted; vars['--n-item-icon-color-collapsed'] = self.itemIconColorCollapsedInverted; vars['--n-item-text-color-horizontal'] = self.itemTextColorHorizontalInverted; vars['--n-item-text-color-hover-horizontal'] = self.itemTextColorHoverHorizontalInverted; vars['--n-item-text-color-active-horizontal'] = self.itemTextColorActiveHorizontalInverted; vars['--n-item-text-color-child-active-horizontal'] = self.itemTextColorChildActiveHorizontalInverted; vars['--n-item-text-color-child-active-hover-horizontal'] = self.itemTextColorChildActiveHoverHorizontalInverted; vars['--n-item-text-color-active-hover-horizontal'] = self.itemTextColorActiveHoverHorizontalInverted; vars['--n-item-icon-color-horizontal'] = self.itemIconColorHorizontalInverted; vars['--n-item-icon-color-hover-horizontal'] = self.itemIconColorHoverHorizontalInverted; vars['--n-item-icon-color-active-horizontal'] = self.itemIconColorActiveHorizontalInverted; vars['--n-item-icon-color-active-hover-horizontal'] = self.itemIconColorActiveHoverHorizontalInverted; vars['--n-item-icon-color-child-active-horizontal'] = self.itemIconColorChildActiveHorizontalInverted; vars['--n-item-icon-color-child-active-hover-horizontal'] = self.itemIconColorChildActiveHoverHorizontalInverted; vars['--n-arrow-color'] = self.arrowColorInverted; vars['--n-arrow-color-hover'] = self.arrowColorHoverInverted; vars['--n-arrow-color-active'] = self.arrowColorActiveInverted; vars['--n-arrow-color-active-hover'] = self.arrowColorActiveHoverInverted; vars['--n-arrow-color-child-active'] = self.arrowColorChildActiveInverted; vars['--n-arrow-color-child-active-hover'] = self.arrowColorChildActiveHoverInverted; vars['--n-item-color-hover'] = self.itemColorHoverInverted; vars['--n-item-color-active'] = self.itemColorActiveInverted; vars['--n-item-color-active-hover'] = self.itemColorActiveHoverInverted; vars['--n-item-color-active-collapsed'] = self.itemColorActiveCollapsedInverted; } else { vars['--n-group-text-color'] = self.groupTextColor; vars['--n-color'] = self.color; vars['--n-item-text-color'] = self.itemTextColor; vars['--n-item-text-color-hover'] = self.itemTextColorHover; vars['--n-item-text-color-active'] = self.itemTextColorActive; vars['--n-item-text-color-child-active'] = self.itemTextColorChildActive; vars['--n-item-text-color-child-active-hover'] = self.itemTextColorChildActiveHover; vars['--n-item-text-color-active-hover'] = self.itemTextColorActiveHover; vars['--n-item-icon-color'] = self.itemIconColor; vars['--n-item-icon-color-hover'] = self.itemIconColorHover; vars['--n-item-icon-color-active'] = self.itemIconColorActive; vars['--n-item-icon-color-active-hover'] = self.itemIconColorActiveHover; vars['--n-item-icon-color-child-active'] = self.itemIconColorChildActive; vars['--n-item-icon-color-child-active-hover'] = self.itemIconColorChildActiveHover; vars['--n-item-icon-color-collapsed'] = self.itemIconColorCollapsed; vars['--n-item-text-color-horizontal'] = self.itemTextColorHorizontal; vars['--n-item-text-color-hover-horizontal'] = self.itemTextColorHoverHorizontal; vars['--n-item-text-color-active-horizontal'] = self.itemTextColorActiveHorizontal; vars['--n-item-text-color-child-active-horizontal'] = self.itemTextColorChildActiveHorizontal; vars['--n-item-text-color-child-active-hover-horizontal'] = self.itemTextColorChildActiveHoverHorizontal; vars['--n-item-text-color-active-hover-horizontal'] = self.itemTextColorActiveHoverHorizontal; vars['--n-item-icon-color-horizontal'] = self.itemIconColorHorizontal; vars['--n-item-icon-color-hover-horizontal'] = self.itemIconColorHoverHorizontal; vars['--n-item-icon-color-active-horizontal'] = self.itemIconColorActiveHorizontal; vars['--n-item-icon-color-active-hover-horizontal'] = self.itemIconColorActiveHoverHorizontal; vars['--n-item-icon-color-child-active-horizontal'] = self.itemIconColorChildActiveHorizontal; vars['--n-item-icon-color-child-active-hover-horizontal'] = self.itemIconColorChildActiveHoverHorizontal; vars['--n-arrow-color'] = self.arrowColor; vars['--n-arrow-color-hover'] = self.arrowColorHover; vars['--n-arrow-color-active'] = self.arrowColorActive; vars['--n-arrow-color-active-hover'] = self.arrowColorActiveHover; vars['--n-arrow-color-child-active'] = self.arrowColorChildActive; vars['--n-arrow-color-child-active-hover'] = self.arrowColorChildActiveHover; vars['--n-item-color-hover'] = self.itemColorHover; vars['--n-item-color-active'] = self.itemColorActive; vars['--n-item-color-active-hover'] = self.itemColorActiveHover; vars['--n-item-color-active-collapsed'] = self.itemColorActiveCollapsed; } return vars; }); const themeClassHandle = inlineThemeDisabled ? (0, _mixins_1.useThemeClass)('menu', (0, vue_1.computed)(() => (props.inverted ? 'a' : 'b')), cssVarsRef, props) : undefined; const ellipsisNodeId = (0, seemly_1.createId)(); const overflowRef = (0, vue_1.ref)(null); const counterRef = (0, vue_1.ref)(null); let isFirstResize = true; const onResize = () => { var _a; if (isFirstResize) { isFirstResize = false; } else { (_a = overflowRef.value) === null || _a === void 0 ? void 0 : _a.sync({ showAllItemsBeforeCalculate: true }); } }; function getCounter() { return document.getElementById(ellipsisNodeId); } const ellipsisFromIndexRef = (0, vue_1.ref)(-1); function onUpdateCount(count) { ellipsisFromIndexRef.value = props.options.length - count; } function onUpdateOverflow(overflow) { if (!overflow) { ellipsisFromIndexRef.value = -1; } } const ellipsisOptionRef = (0, vue_1.computed)(() => { const ellipsisFromIndex = ellipsisFromIndexRef.value; const option = { children: ellipsisFromIndex === -1 ? [] : props.options.slice(ellipsisFromIndex) }; return option; }); const ellipsisTreeMateRef = (0, vue_1.computed)(() => { const { childrenField, disabledField, keyField } = props; return (0, treemate_1.createTreeMate)([ellipsisOptionRef.value], { getIgnored(node) { return (0, utils_1.isIgnoredNode)(node); }, getChildren(node) { return node[childrenField]; }, getDisabled(node) { return node[disabledField]; }, getKey(node) { var _a; return (_a = node[keyField]) !== null && _a !== void 0 ? _a : node.name; } }); }); const emptyTmNodeRef = (0, vue_1.computed)(() => { return (0, treemate_1.createTreeMate)([ {} ]).treeNodes[0]; }); function renderCounter() { var _a; if (ellipsisFromIndexRef.value === -1) { // Only a placeholder return ((0, vue_1.h)(Submenu_1.NSubmenu, { root: true, level: 0, key: "__ellpisisGroupPlaceholder__", internalKey: "__ellpisisGroupPlaceholder__", title: "\u00B7\u00B7\u00B7", tmNode: emptyTmNodeRef.value, domId: ellipsisNodeId, isEllipsisPlaceholder: true })); } const tmNode = ellipsisTreeMateRef.value.treeNodes[0]; const activePath = activePathRef.value; const childActive = !!((_a = tmNode.children) === null || _a === void 0 ? void 0 : _a.some((tmNode) => { return activePath.includes(tmNode.key); })); return ((0, vue_1.h)(Submenu_1.NSubmenu, { level: 0, root: true, key: "__ellpisisGroup__", internalKey: "__ellpisisGroup__", title: "\u00B7\u00B7\u00B7", virtualChildActive: childActive, tmNode: tmNode, domId: ellipsisNodeId, rawNodes: tmNode.rawNode.children || [], tmNodes: tmNode.children || [], isEllipsisPlaceholder: true })); } return { mergedClsPrefix: mergedClsPrefixRef, controlledExpandedKeys: controlledExpandedKeysRef, uncontrolledExpanededKeys: uncontrolledExpandedKeysRef, mergedExpandedKeys: mergedExpandedKeysRef, uncontrolledValue: uncontrolledValueRef, mergedValue: mergedValueRef, activePath: activePathRef, tmNodes: tmNodesRef, mergedTheme: themeRef, mergedCollapsed: mergedCollapsedRef, cssVars: inlineThemeDisabled ? undefined : cssVarsRef, themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass, overflowRef, counterRef, updateCounter: () => { }, onResize, onUpdateOverflow, onUpdateCount, renderCounter, getCounter, onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender, showOption, deriveResponsiveState: onResize }; }, render() { const { mergedClsPrefix, mode, themeClass, onRender } = this; onRender === null || onRender === void 0 ? void 0 : onRender(); const renderMenuItemNodes = () => this.tmNodes.map(tmNode => (0, utils_1.itemRenderer)(tmNode, this.$props)); const horizontal = mode === 'horizontal'; const finalResponsive = horizontal && this.responsive; const renderMainNode = () => (0, vue_1.h)('div', (0, vue_1.mergeProps)(this.$attrs, { role: mode === 'horizontal' ? 'menubar' : 'menu', class: [ `${mergedClsPrefix}-menu`, themeClass, `${mergedClsPrefix}-menu--${mode}`, finalResponsive && `${mergedClsPrefix}-menu--responsive`, this.mergedCollapsed && `${mergedClsPrefix}-menu--collapsed` ], style: this.cssVars }), finalResponsive ? ((0, vue_1.h)(vueuc_1.VOverflow, { ref: "overflowRef", onUpdateOverflow: this.onUpdateOverflow, getCounter: this.getCounter, onUpdateCount: this.onUpdateCount, updateCounter: this.updateCounter, style: { width: '100%', display: 'flex', overflow: 'hidden' } }, { default: renderMenuItemNodes, counter: this.renderCounter })) : (renderMenuItemNodes())); return finalResponsive ? ((0, vue_1.h)(vueuc_1.VResizeObserver, { onResize: this.onResize }, { default: renderMainNode })) : (renderMainNode()); } });