feat: update vc-menu
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 => {
|
||||
this.firstActiveItem = 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,
|
||||
multiple,
|
||||
inputValue,
|
||||
visible,
|
||||
},
|
||||
on: {
|
||||
popupFocus,
|
||||
},
|
||||
menuItems: props.options,
|
||||
multiple,
|
||||
inputValue,
|
||||
visible,
|
||||
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…
Reference in New Issue