feat: update vc-menu

pull/2502/head
tanjinzhou 4 years ago
parent 93bde3fb67
commit 19e4e27814

@ -2,14 +2,15 @@ import raf from 'raf';
import PropTypes from '../_util/vue-types';
import Menu from '../vc-menu';
import scrollIntoView from 'dom-scroll-into-view';
import { getSelectKeys, preventDefaultEvent } from './util';
import { getSelectKeys, preventDefaultEvent, saveRef } from './util';
import { cloneElement } from '../_util/vnode';
import BaseMixin from '../_util/BaseMixin';
import { getSlotOptions, getComponentFromProp, getListeners } from '../_util/props-util';
import { getSlotOptions, findDOMNode } from '../_util/props-util';
export default {
name: 'DropdownMenu',
mixins: [BaseMixin],
inheritAttrs: false,
props: {
ariaId: PropTypes.string,
defaultActiveFirstOption: PropTypes.bool,
@ -42,6 +43,7 @@ export default {
created() {
this.rafInstance = null;
this.saveMenuRef = saveRef(this, 'menuRef');
this.lastInputValue = this.$props.inputValue;
this.lastVisible = false;
},
@ -86,51 +88,36 @@ export default {
// Delay to scroll since current frame item position is not ready when pre view is by filter
// https://github.com/ant-design/ant-design/issues/11268#issuecomment-406634462
this.rafInstance = raf(() => {
scrollIntoView(itemComponent, this.$refs.menuRef.$el, scrollIntoViewOpts);
scrollIntoView(itemComponent, findDOMNode(this.menuRef), scrollIntoViewOpts);
});
},
renderMenu() {
const props = this.$props;
const props = { ...this.$props, ...this.$attrs };
const {
menuItems,
menuItemSelectedIcon,
defaultActiveFirstOption,
value,
prefixCls,
multiple,
onMenuSelect,
inputValue,
firstActiveValue,
dropdownMenuStyle,
backfillValue,
onMenuDeselect,
visible,
} = props;
const menuItemSelectedIcon = getComponentFromProp(this, 'menuItemSelectedIcon');
const { menuDeselect, menuSelect, popupScroll } = getListeners(this);
const firstActiveValue = this.firstActiveValue;
if (menuItems && menuItems.length) {
const selectedKeys = getSelectKeys(menuItems, value);
const menuProps = {
props: {
multiple,
itemIcon: multiple ? menuItemSelectedIcon : null,
selectedKeys,
prefixCls: `${prefixCls}-menu`,
},
on: {},
style: dropdownMenuStyle,
ref: 'menuRef',
attrs: {
role: 'listbox',
},
};
if (popupScroll) {
menuProps.on.scroll = popupScroll;
}
const menuProps = {};
if (multiple) {
menuProps.on.deselect = menuDeselect;
menuProps.on.select = menuSelect;
menuProps.onDeselect = onMenuDeselect;
menuProps.onSelect = onMenuSelect;
} else {
menuProps.on.click = menuSelect;
menuProps.onClick = onMenuSelect;
}
const value = this.value;
const selectedKeys = getSelectKeys(menuItems, value);
const activeKeyProps = {};
let defaultActiveFirst = defaultActiveFirstOption;
@ -155,20 +142,16 @@ export default {
) {
foundFirst = true;
return cloneElement(item, {
directives: [
{
name: 'ant-ref',
value: ref => {
ref: ref => {
this.firstActiveItem = ref;
},
},
],
});
}
return item;
};
clonedMenuItems = menuItems.map(item => {
debugger;
if (getSlotOptions(item).isMenuItemGroup) {
const children = item.componentOptions.children.map(clone);
return cloneElement(item, { children });
@ -187,15 +170,29 @@ export default {
if (inputValue !== this.lastInputValue && (!lastValue || lastValue !== backfillValue)) {
activeKeyProps.activeKey = '';
}
menuProps.props = { ...activeKeyProps, ...menuProps.props, defaultActiveFirst };
return <Menu {...menuProps}>{clonedMenuItems}</Menu>;
return (
<Menu
ref={this.saveMenuRef}
style={this.dropdownMenuStyle}
defaultActiveFirst={defaultActiveFirst}
role="listbox"
itemIcon={multiple ? menuItemSelectedIcon : null}
{...activeKeyProps}
multiple={multiple}
{...menuProps}
selectedKeys={selectedKeys}
prefixCls={`${prefixCls}-menu`}
>
{clonedMenuItems}
</Menu>
);
}
return null;
},
},
render() {
const renderMenu = this.renderMenu();
const { popupFocus, popupScroll } = getListeners(this);
const { onPopupFocus, onPopupScroll } = this.$attrs;
return renderMenu ? (
<div
style={{
@ -204,10 +201,9 @@ export default {
}}
id={this.$props.ariaId}
tabIndex="-1"
onFocus={popupFocus}
onFocus={onPopupFocus}
onMousedown={preventDefaultEvent}
onScroll={popupScroll}
ref="menuContainer"
onScroll={onPopupScroll}
>
{renderMenu}
</div>

@ -81,6 +81,7 @@ const Select = {
OptGroup,
name: 'Select',
mixins: [BaseMixin],
inheritAttrs: false,
props: {
...SelectPropTypes,
prefixCls: SelectPropTypes.prefixCls.def('rc-select'),
@ -112,10 +113,10 @@ const Select = {
// onDeselect: noop,
// onInputKeydown: noop,
},
model: {
prop: 'value',
event: 'change',
},
// model: {
// prop: 'value',
// event: 'change',
// },
created() {
this.saveInputRef = saveRef(this, 'inputRef');
this.saveInputMirrorRef = saveRef(this, 'inputMirrorRef');
@ -1667,14 +1668,7 @@ const Select = {
onMouseleave={mouseleave}
showAction={props.showAction}
menuItemSelectedIcon={getComponentFromProp(this, 'menuItemSelectedIcon')}
{...{
directives: [
{
name: 'ant-ref',
value: this.saveSelectTriggerRef,
},
],
}}
ref={this.saveSelectTriggerRef}
dropdownRender={props.dropdownRender}
ariaId={this.$data._ariaId}
>

@ -5,7 +5,7 @@ import PropTypes from '../_util/vue-types';
import DropdownMenu from './DropdownMenu';
import { isSingleMode, saveRef } from './util';
import BaseMixin from '../_util/BaseMixin';
import { getListeners } from '../_util/props-util';
import { findDOMNode, getSlot } from '../_util/props-util';
const BUILT_IN_PLACEMENTS = {
bottomLeft: {
@ -29,6 +29,7 @@ const BUILT_IN_PLACEMENTS = {
export default {
name: 'SelectTrigger',
mixins: [BaseMixin],
inheritAttrs: false,
props: {
// onPopupFocus: PropTypes.func,
// onPopupScroll: PropTypes.func,
@ -89,7 +90,7 @@ export default {
setDropdownWidth() {
this.cancelRafInstance();
this.rafInstance = raf(() => {
const width = this.$el.offsetWidth;
const width = findDOMNode(this).offsetWidth;
if (width !== this.dropdownWidth) {
this.setState({ dropdownWidth: width });
}
@ -101,7 +102,7 @@ export default {
}
},
getInnerMenu() {
return this.dropdownMenuRef && this.dropdownMenuRef.$refs.menuRef;
return this.dropdownMenuRef && this.dropdownMenuRef.menuRef;
},
getPopupDOMNode() {
@ -109,45 +110,25 @@ export default {
},
getDropdownElement(newProps) {
const {
value,
firstActiveValue,
defaultActiveFirstOption,
dropdownMenuStyle,
getDropdownPrefixCls,
backfillValue,
menuItemSelectedIcon,
} = this;
const { menuSelect, menuDeselect, popupScroll } = getListeners(this);
const props = this.$props;
const props = { ...this.$props, ...this.$attrs };
const { dropdownRender, ariaId } = props;
const dropdownMenuProps = {
props: {
...newProps.props,
ariaId,
prefixCls: getDropdownPrefixCls(),
value,
firstActiveValue,
defaultActiveFirstOption,
dropdownMenuStyle,
backfillValue,
menuItemSelectedIcon,
},
on: {
...newProps.on,
menuSelect,
menuDeselect,
popupScroll,
},
directives: [
{
name: 'ant-ref',
value: this.saveDropdownMenuRef,
},
],
};
const menuNode = <DropdownMenu {...dropdownMenuProps} />;
const menuNode = (
<DropdownMenu
ref={this.saveDropdownMenuRef}
{...newProps}
ariaId={ariaId}
prefixCls={this.getDropdownPrefixCls()}
onMenuSelect={props.onMenuSelect}
onMenuDeselect={props.onMenuDeselect}
onPopupScroll={props.onPopupScroll}
value={props.value}
backfillValue={props.backfillValue}
firstActiveValue={props.firstActiveValue}
defaultActiveFirstOption={props.defaultActiveFirstOption}
dropdownMenuStyle={props.dropdownMenuStyle}
menuItemSelectedIcon={props.menuItemSelectedIcon}
/>
);
if (dropdownRender) {
return dropdownRender(menuNode, props);
@ -170,7 +151,7 @@ export default {
},
render() {
const { $props, $slots } = this;
const { onPopupFocus, empty, ...props } = { ...this.$props, ...this.$attrs };
const {
multiple,
visible,
@ -181,12 +162,8 @@ export default {
dropdownClassName,
dropdownStyle,
dropdownMatchSelectWidth,
options,
getPopupContainer,
showAction,
empty,
} = $props;
const { mouseenter, mouseleave, popupFocus, dropdownVisibleChange } = getListeners(this);
} = props;
//const { mouseenter, mouseleave, popupFocus, dropdownVisibleChange } = getListeners(this);
const dropdownPrefixCls = this.getDropdownPrefixCls();
const popupClassName = {
[dropdownClassName]: !!dropdownClassName,
@ -194,20 +171,16 @@ export default {
[`${dropdownPrefixCls}--empty`]: empty,
};
const popupElement = this.getDropdownElement({
props: {
menuItems: options,
menuItems: props.options,
multiple,
inputValue,
visible,
},
on: {
popupFocus,
},
onPopupFocus,
});
let hideAction;
if (disabled) {
hideAction = [];
} else if (isSingleMode($props) && !showSearch) {
} else if (isSingleMode(props) && !showSearch) {
hideAction = ['click'];
} else {
hideAction = ['blur'];
@ -217,42 +190,25 @@ export default {
if (this.dropdownWidth) {
popupStyle[widthProp] = `${this.dropdownWidth}px`;
}
const triggerProps = {
props: {
...$props,
showAction: disabled ? [] : showAction,
hideAction,
ref: 'triggerRef',
popupPlacement: 'bottomLeft',
builtinPlacements: BUILT_IN_PLACEMENTS,
prefixCls: dropdownPrefixCls,
popupTransitionName: this.getDropdownTransitionName(),
popupAlign: dropdownAlign,
popupVisible: visible,
getPopupContainer,
popupClassName: classnames(popupClassName),
popupStyle,
},
on: {
popupVisibleChange: dropdownVisibleChange,
},
directives: [
{
name: 'ant-ref',
value: this.saveTriggerRef,
},
],
};
if (mouseenter) {
triggerProps.on.mouseenter = mouseenter;
}
if (mouseleave) {
triggerProps.on.mouseleave = mouseleave;
}
return (
<Trigger {...triggerProps}>
{$slots.default}
<template slot="popup">{popupElement}</template>
<Trigger
{...props}
showAction={disabled ? [] : this.$props.showAction}
hideAction={hideAction}
ref={this.saveTriggerRef}
popupPlacement="bottomLeft"
builtinPlacements={BUILT_IN_PLACEMENTS}
prefixCls={dropdownPrefixCls}
popupTransitionName={this.getDropdownTransitionName()}
onPopupVisibleChange={props.onDropdownVisibleChange}
popup={popupElement}
popupAlign={dropdownAlign}
popupVisible={visible}
getPopupContainer={props.getPopupContainer}
popupClassName={classnames(popupClassName)}
popupStyle={popupStyle}
>
{getSlot(this)[0]}
</Trigger>
);
},

Loading…
Cancel
Save