Update dependendies (#8150)

* deps: upgrade rc-menu, and close: #2837

* test: update snapshots

* Update rc-calendar

* Update rc-cascader

* Update rc-dialog

* Update dropdown

* Update rc-select@7.1.0

* Update rc-slider

* Update rc-time-picker

* Update rc-tooltip

* Update rc-tree-select

* Mock rc-trigger and Portal

* Fix animation warning when inlineCollapsed changes

* fix: should use SubMenu[popupClassName]

* Fix typescript error

* Fix lint

* fix: style for menu

* Mock rc-trigger for React 15

* Remvoe allow_failures
pull/8166/head
Wei Zhu 7 years ago committed by GitHub
parent fe7386746c
commit 55c85f77a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -19,8 +19,6 @@ matrix:
- env: REACT=15 TEST_TYPE=test:es
- env: REACT=15 TEST_TYPE=test:dom
- env: REACT=15 TEST_TYPE=test:node
allow_failures:
- env: REACT=16 TEST_TYPE=test:dist
before_script:
- scripts/install-react.sh

@ -17,6 +17,15 @@ timeline: true
---
## 3.0.0
- Select
- 单选和多选模式 Option 支持 number。
- 新增 `maxTagCount``maxTagPlaceholder`
- 新增 `showAction`
- 新增 `onMouseEnter``onMouseLeave`
- 新增 `focus()`、`blur()` 和 `autoFocus`
## 2.13.9
`2017-11-06`

@ -234,7 +234,7 @@ exports[`RangePicker show month panel according to value 1`] = `
</div>
</td>
<td
class="ant-calendar-cell ant-calendar-selected-day"
class="ant-calendar-cell ant-calendar-selected-start-date ant-calendar-selected-end-date ant-calendar-selected-day"
role="gridcell"
title="2000年1月1日"
>
@ -1739,7 +1739,7 @@ exports[`RangePicker switch to corresponding month panel when click presetted ra
</div>
</td>
<td
class="ant-calendar-cell ant-calendar-selected-day"
class="ant-calendar-cell ant-calendar-selected-start-date ant-calendar-selected-end-date ant-calendar-selected-day"
role="gridcell"
title="2000年1月1日"
>

@ -139,13 +139,13 @@ exports[`renders ./components/layout/demo/custom-trigger.md correctly 1`] = `
/>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-dark ant-menu-root"
class="ant-menu ant-menu-dark ant-menu-root ant-menu-inline"
role="menu"
tabindex="0"
>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
style="padding-left:24px"
>
@ -219,7 +219,7 @@ exports[`renders ./components/layout/demo/fixed.md correctly 1`] = `
/>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-horizontal ant-menu-dark ant-menu-root"
class="ant-menu ant-menu-dark ant-menu-root ant-menu-horizontal"
role="menu"
style="line-height:64px"
tabindex="0"
@ -233,7 +233,7 @@ exports[`renders ./components/layout/demo/fixed.md correctly 1`] = `
</li>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
>
nav 2
@ -323,7 +323,7 @@ exports[`renders ./components/layout/demo/fixed-sider.md correctly 1`] = `
/>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-dark ant-menu-root"
class="ant-menu ant-menu-dark ant-menu-root ant-menu-inline"
role="menu"
tabindex="0"
>
@ -374,7 +374,7 @@ exports[`renders ./components/layout/demo/fixed-sider.md correctly 1`] = `
</li>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
style="padding-left:24px"
>
@ -588,7 +588,7 @@ exports[`renders ./components/layout/demo/responsive.md correctly 1`] = `
/>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-dark ant-menu-root"
class="ant-menu ant-menu-dark ant-menu-root ant-menu-inline"
role="menu"
tabindex="0"
>
@ -639,7 +639,7 @@ exports[`renders ./components/layout/demo/responsive.md correctly 1`] = `
</li>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
style="padding-left:24px"
>
@ -699,13 +699,13 @@ exports[`renders ./components/layout/demo/side.md correctly 1`] = `
/>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-dark ant-menu-root"
class="ant-menu ant-menu-dark ant-menu-root ant-menu-inline"
role="menu"
tabindex="0"
>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
style="padding-left:24px"
>
@ -730,7 +730,7 @@ exports[`renders ./components/layout/demo/side.md correctly 1`] = `
</span>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -753,7 +753,7 @@ exports[`renders ./components/layout/demo/side.md correctly 1`] = `
</div>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -867,7 +867,7 @@ exports[`renders ./components/layout/demo/top.md correctly 1`] = `
/>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-horizontal ant-menu-dark ant-menu-root"
class="ant-menu ant-menu-dark ant-menu-root ant-menu-horizontal"
role="menu"
style="line-height:64px"
tabindex="0"
@ -881,7 +881,7 @@ exports[`renders ./components/layout/demo/top.md correctly 1`] = `
</li>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
>
nav 2
@ -967,7 +967,7 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
/>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-horizontal ant-menu-dark ant-menu-root"
class="ant-menu ant-menu-dark ant-menu-root ant-menu-horizontal"
role="menu"
style="line-height:64px"
tabindex="0"
@ -981,7 +981,7 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
</li>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
>
nav 2
@ -1053,13 +1053,13 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-light ant-menu-root"
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
role="menu"
style="height:100%"
tabindex="0"
>
<li
class="ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected"
>
<div
aria-expanded="true"
@ -1080,13 +1080,13 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
</div>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-sub"
class="ant-menu ant-menu-sub ant-menu-inline"
id="sub1$Menu"
role="menu"
>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
style="padding-left:48px"
>
@ -1119,7 +1119,7 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
</ul>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -1140,7 +1140,7 @@ exports[`renders ./components/layout/demo/top-side.md correctly 1`] = `
</div>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -1192,7 +1192,7 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
/>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-horizontal ant-menu-dark ant-menu-root"
class="ant-menu ant-menu-dark ant-menu-root ant-menu-horizontal"
role="menu"
style="line-height:64px"
tabindex="0"
@ -1206,7 +1206,7 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
</li>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
>
nav 2
@ -1232,13 +1232,13 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-light ant-menu-root"
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
role="menu"
style="height:100%;border-right:0"
tabindex="0"
>
<li
class="ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected"
>
<div
aria-expanded="true"
@ -1259,13 +1259,13 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
</div>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-sub"
class="ant-menu ant-menu-sub ant-menu-inline"
id="sub1$Menu"
role="menu"
>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
style="padding-left:48px"
>
@ -1298,7 +1298,7 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
</ul>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -1319,7 +1319,7 @@ exports[`renders ./components/layout/demo/top-side-2.md correctly 1`] = `
</div>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"

@ -0,0 +1,22 @@
import React from 'react';
import PropTypes from 'prop-types';
import { SubMenu as RcSubMenu } from 'rc-menu';
import classNames from 'classnames';
class SubMenu extends React.Component<any, any> {
static contextTypes = {
antdMenuTheme: PropTypes.string,
};
render() {
const { rootPrefixCls, className } = this.props;
const theme = this.context.antdMenuTheme;
return (
<RcSubMenu
{...this.props}
popupClassName={classNames(`${rootPrefixCls}-${theme}`, className)}
/>
);
}
}
export default SubMenu;

@ -3,13 +3,13 @@
exports[`renders ./components/menu/demo/horizontal.md correctly 1`] = `
<ul
aria-activedescendant=""
class="ant-menu ant-menu-horizontal ant-menu-light ant-menu-root"
class="ant-menu ant-menu-light ant-menu-root ant-menu-horizontal"
role="menu"
tabindex="0"
>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
>
<i
@ -20,7 +20,7 @@ exports[`renders ./components/menu/demo/horizontal.md correctly 1`] = `
<li
aria-disabled="true"
aria-selected="false"
class="ant-menu-item-disabled ant-menu-item"
class="ant-menu-item ant-menu-item-disabled"
role="menuitem"
>
<i
@ -29,7 +29,7 @@ exports[`renders ./components/menu/demo/horizontal.md correctly 1`] = `
Navigation Two
</li>
<li
class="ant-menu-submenu-horizontal ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-horizontal"
>
<div
aria-expanded="false"
@ -67,13 +67,13 @@ exports[`renders ./components/menu/demo/horizontal.md correctly 1`] = `
exports[`renders ./components/menu/demo/inline.md correctly 1`] = `
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-light ant-menu-root"
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
role="menu"
style="width:256px"
tabindex="0"
>
<li
class="ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected"
>
<div
aria-expanded="true"
@ -96,7 +96,7 @@ exports[`renders ./components/menu/demo/inline.md correctly 1`] = `
</div>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-sub"
class="ant-menu ant-menu-sub ant-menu-inline"
id="sub1$Menu"
role="menu"
>
@ -114,7 +114,7 @@ exports[`renders ./components/menu/demo/inline.md correctly 1`] = `
>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
style="padding-left:48px"
>
@ -163,7 +163,7 @@ exports[`renders ./components/menu/demo/inline.md correctly 1`] = `
</ul>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -186,7 +186,7 @@ exports[`renders ./components/menu/demo/inline.md correctly 1`] = `
</div>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -226,13 +226,13 @@ exports[`renders ./components/menu/demo/inline-collapsed.md correctly 1`] = `
</button>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-dark ant-menu-root"
class="ant-menu ant-menu-dark ant-menu-root ant-menu-inline"
role="menu"
tabindex="0"
>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
style="padding-left:24px"
>
@ -270,7 +270,7 @@ exports[`renders ./components/menu/demo/inline-collapsed.md correctly 1`] = `
</span>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open"
>
<div
aria-expanded="true"
@ -293,7 +293,7 @@ exports[`renders ./components/menu/demo/inline-collapsed.md correctly 1`] = `
</div>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-sub"
class="ant-menu ant-menu-sub ant-menu-inline"
id="sub1$Menu"
role="menu"
>
@ -332,7 +332,7 @@ exports[`renders ./components/menu/demo/inline-collapsed.md correctly 1`] = `
</ul>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -361,13 +361,13 @@ exports[`renders ./components/menu/demo/inline-collapsed.md correctly 1`] = `
exports[`renders ./components/menu/demo/sider-current.md correctly 1`] = `
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-light ant-menu-root"
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
role="menu"
style="width:256px"
tabindex="0"
>
<li
class="ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open"
>
<div
aria-expanded="true"
@ -390,7 +390,7 @@ exports[`renders ./components/menu/demo/sider-current.md correctly 1`] = `
</div>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-sub"
class="ant-menu ant-menu-sub ant-menu-inline"
id="sub1$Menu"
role="menu"
>
@ -429,7 +429,7 @@ exports[`renders ./components/menu/demo/sider-current.md correctly 1`] = `
</ul>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -452,7 +452,7 @@ exports[`renders ./components/menu/demo/sider-current.md correctly 1`] = `
</div>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -505,14 +505,14 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
<br />
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-light ant-menu-root"
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
role="menu"
style="width:256px"
tabindex="0"
>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
style="padding-left:24px"
>
@ -533,7 +533,7 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
Navigation Two
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open"
>
<div
aria-expanded="true"
@ -556,7 +556,7 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
</div>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-sub"
class="ant-menu ant-menu-sub ant-menu-inline"
id="sub1$Menu"
role="menu"
>
@ -577,7 +577,7 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
Option 4
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -596,7 +596,7 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
</ul>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -639,13 +639,13 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
<br />
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-dark ant-menu-root"
class="ant-menu ant-menu-dark ant-menu-root ant-menu-inline"
role="menu"
style="width:256px"
tabindex="0"
>
<li
class="ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected"
>
<div
aria-expanded="true"
@ -668,13 +668,13 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
</div>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-sub"
class="ant-menu ant-menu-sub ant-menu-inline"
id="sub1$Menu"
role="menu"
>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
class="ant-menu-item ant-menu-item-selected"
role="menuitem"
style="padding-left:48px"
>
@ -707,7 +707,7 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
</ul>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -730,7 +730,7 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
</div>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-inline"
>
<div
aria-expanded="false"
@ -759,13 +759,13 @@ exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
exports[`renders ./components/menu/demo/vertical.md correctly 1`] = `
<ul
aria-activedescendant=""
class="ant-menu ant-menu-vertical ant-menu-light ant-menu-root"
class="ant-menu ant-menu-light ant-menu-root ant-menu-vertical"
role="menu"
style="width:256px"
tabindex="0"
>
<li
class="ant-menu-submenu-vertical ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-vertical"
>
<div
aria-expanded="false"
@ -787,7 +787,7 @@ exports[`renders ./components/menu/demo/vertical.md correctly 1`] = `
</div>
</li>
<li
class="ant-menu-submenu-vertical ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-vertical"
>
<div
aria-expanded="false"
@ -809,7 +809,7 @@ exports[`renders ./components/menu/demo/vertical.md correctly 1`] = `
</div>
</li>
<li
class="ant-menu-submenu-vertical ant-menu-submenu"
class="ant-menu-submenu ant-menu-submenu-vertical"
>
<div
aria-expanded="false"

@ -4,7 +4,6 @@ import Menu from '..';
import Icon from '../../icon';
const { SubMenu } = Menu;
const delay = timeout => new Promise(resolve => setTimeout(resolve, timeout));
describe('Menu', () => {
it('should accept defaultOpenKeys in mode horizontal', () => {
@ -46,7 +45,7 @@ describe('Menu', () => {
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
});
it('should accept openKeys in mode horizontal', () => {
it('horizontal', () => {
const wrapper = mount(
<Menu openKeys={['1']} mode="horizontal" openTransitionName="">
<SubMenu key="1" title="submenu1">
@ -64,7 +63,7 @@ describe('Menu', () => {
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(true);
});
it('should accept openKeys in mode inline', () => {
it('inline', () => {
const wrapper = mount(
<Menu openKeys={['1']} mode="inline" openAnimation="">
<SubMenu key="1" title="submenu1">
@ -82,7 +81,7 @@ describe('Menu', () => {
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(true);
});
it('should accept openKeys in mode vertical', () => {
it('vertical', () => {
const wrapper = mount(
<Menu openKeys={['1']} mode="vertical" openTransitionName="">
<SubMenu key="1" title="submenu1">
@ -133,7 +132,9 @@ describe('Menu', () => {
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
});
it('should always follow openKeys when mode is switched', () => {
it('should always follow openKeys when mode is switched', async () => {
jest.useFakeTimers();
const wrapper = mount(
<Menu defaultOpenKeys={['1']} mode="inline">
<Menu.Item key="menu1">
@ -150,76 +151,97 @@ describe('Menu', () => {
</SubMenu>
</Menu>
);
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-inline')).toBe(true);
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false);
wrapper.setProps({ inlineCollapsed: true });
setTimeout(() => {
// 动画结束后套样式;
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-vertical')).toBe(true);
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(true);
wrapper.setProps({ inlineCollapsed: false });
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-inline')).toBe(true);
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false);
}, 300);
});
it('should open submenu when click submenu title (inline)', async () => {
const wrapper = mount(
<Menu mode="inline">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>
);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
wrapper.find('.ant-menu-submenu-title').simulate('click');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(true);
wrapper.find('.ant-menu-submenu-title').simulate('click');
await delay(300);
wrapper.setProps({ inlineCollapsed: true });
// 动画结束后套样式;
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
});
it('should open submenu when hover submenu title (vertical)', async () => {
const wrapper = mount(
<Menu mode="vertical">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>
);
expect(wrapper.find('.ant-menu').at(0).hasClass('ant-menu-vertical')).toBe(true);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
wrapper.find('.ant-menu-submenu-title').simulate('mouseenter');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(true);
wrapper.find('.ant-menu-submenu').simulate('mouseleave');
await delay(300);
wrapper.setProps({ inlineCollapsed: false });
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-inline')).toBe(true);
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false);
jest.useRealTimers();
});
it('should open submenu when hover submenu title (horizontal)', async () => {
const wrapper = mount(
<Menu mode="horizontal">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>
);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
wrapper.find('.ant-menu-submenu-title').simulate('mouseenter');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(true);
wrapper.find('.ant-menu-submenu').simulate('mouseleave');
await delay(300);
wrapper.update();
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
describe('open submenu when click submenu title', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
const toggleMenu = (wrapper, index, event) => {
wrapper.find('.ant-menu-submenu-title').at(index).simulate(event);
jest.runAllTimers();
wrapper.update();
};
it('inline', () => {
const wrapper = mount(
<Menu mode="inline">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>
);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
toggleMenu(wrapper, 0, 'click');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(true);
toggleMenu(wrapper, 0, 'click');
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
});
it('vertical', () => {
const wrapper = mount(
<Menu mode="vertical">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>
);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
toggleMenu(wrapper, 0, 'mouseenter');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(true);
toggleMenu(wrapper, 0, 'mouseleave');
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
});
it('horizontal', () => {
jest.useFakeTimers();
const wrapper = mount(
<Menu mode="horizontal">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>
);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
toggleMenu(wrapper, 0, 'mouseenter');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(true);
toggleMenu(wrapper, 0, 'mouseleave');
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
});
});
});

@ -32,7 +32,7 @@ More layouts with navigation: [layout](/components/layout).
| defaultSelectedKeys | array with the keys of default selected menu items | string\[] | |
| inlineCollapsed | specifies the collapsed status when menu is inline mode | boolean | - |
| inlineIndent | indent px of inline menu item on each level | number | 24 |
| mode | type of the menu; `vertical`, `horizontal`, and `inline` modes are supported | string: `vertical` \| `horizontal` \| `inline` | `vertical` |
| mode | type of the menu; `vertical`, `horizontal`, and `inline` modes are supported | string: `vertical` \| `vertical-right` \| `horizontal` \| `inline` | `vertical` |
| multiple | Allow selection of multiple items | boolean | false |
| openKeys | array with the keys of currently opened sub menus | string\[] | |
| selectable | Allow to be selected | boolean | true |
@ -44,6 +44,8 @@ More layouts with navigation: [layout](/components/layout).
| onDeselect | callback executed when a menu item is deselected, only supported for multiple mode | function({ item, key, selectedKeys }) | - |
| onOpenChange | called when open/close sub menu | function(openKeys: string\[]) | noop |
| onSelect | callback executed when a menu item is selected | function({ item, key, selectedKeys }) | none |
| subMenuOpenDelay | delay time to show submenu when mouse enter, unit: second | number | 0 |
| subMenuCloseDelay | delay time to hide submenu when mouse leave, unit: second | number | 0.1 |
> More options in [rc-menu](https://github.com/react-component/menu#api)

@ -1,9 +1,10 @@
import React from 'react';
import RcMenu, { Divider, SubMenu, ItemGroup } from 'rc-menu';
import RcMenu, { Divider, ItemGroup } from 'rc-menu';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import animation from '../_util/openAnimation';
import warning from '../_util/warning';
import SubMenu from './SubMenu';
import Item from './MenuItem';
export interface SelectParam {
@ -23,10 +24,8 @@ export interface ClickParam {
export interface MenuProps {
id?: string;
/** `light` `dark` */
theme?: 'light' | 'dark';
/** enum: `vertical` `horizontal` `inline` */
mode?: 'vertical' | 'horizontal' | 'inline';
mode?: 'vertical' | 'vertical-left' | 'vertical-right' | 'horizontal' | 'inline';
selectable?: boolean;
selectedKeys?: Array<string>;
defaultSelectedKeys?: Array<string>;
@ -58,6 +57,7 @@ export default class Menu extends React.Component<MenuProps, any> {
};
static childContextTypes = {
inlineCollapsed: PropTypes.bool,
antdMenuTheme: PropTypes.string,
};
static contextTypes = {
siderCollapsed: PropTypes.bool,
@ -92,6 +92,7 @@ export default class Menu extends React.Component<MenuProps, any> {
getChildContext() {
return {
inlineCollapsed: this.getInlineCollapsed(),
antdMenuTheme: this.props.theme,
};
}
componentWillReceiveProps(nextProps, nextContext) {
@ -160,6 +161,8 @@ export default class Menu extends React.Component<MenuProps, any> {
menuOpenAnimation = 'slide-up';
break;
case 'vertical':
case 'vertical-left':
case 'vertical-right':
// When mode switch from inline
// submenu should hide without animation
if (this.switchModeFromInline) {
@ -176,6 +179,11 @@ export default class Menu extends React.Component<MenuProps, any> {
// Make sure inline menu leave animation finished before mode is switched
this.switchModeFromInline = false;
this.setState({});
// when inlineCollapsed change false to true, all submenu will be unmounted,
// so that we don't need handle animation leaving.
if (this.getRealMenuMode() === 'vertical') {
return;
}
done();
}),
};

@ -33,7 +33,7 @@ subtitle: 导航菜单
| defaultSelectedKeys | 初始选中的菜单项 key 数组 | string\[] | |
| inlineCollapsed | inline 时菜单是否收起状态 | boolean | - |
| inlineIndent | inline 模式的菜单缩进宽度 | number | 24 |
| mode | 菜单类型,现在支持垂直、水平、和内嵌模式三种 | string: `vertical` `horizontal` `inline` | `vertical` |
| mode | 菜单类型,现在支持垂直、水平、和内嵌模式三种 | string: `vertical` `vertical-right` `horizontal` `inline` | `vertical` |
| multiple | 是否允许多选 | boolean | false |
| openKeys | 当前展开的 SubMenu 菜单项 key 数组 | string\[] | |
| selectable | 是否允许选中 | boolean | true |
@ -44,6 +44,8 @@ subtitle: 导航菜单
| onDeselect | 取消选中时调用,仅在 multiple 生效 | function({ item, key, selectedKeys }) | - |
| onOpenChange | SubMenu 展开/关闭的回调 | function(openKeys: string\[]) | noop |
| onSelect | 被选中时调用 | function({ item, key, selectedKeys }) | 无   |
| subMenuOpenDelay | 用户鼠标进入子菜单后开启延时,单位:秒 | number | 0 |
| subMenuCloseDelay | 用户鼠标离开子菜单后关闭延时,单位:秒 | number | 0.1 |
> More options in [rc-menu](https://github.com/react-component/menu#api)

@ -12,7 +12,6 @@
margin-bottom: 0;
padding-left: 0; // Override default ul/ol
list-style: none;
z-index: @zindex-dropdown;
box-shadow: @box-shadow-base;
background: @component-background;
line-height: 0; // Fix display inline-block gap
@ -102,10 +101,6 @@
color: @primary-color;
}
&:not(&-inline) &-submenu-open {
z-index: @zindex-dropdown;
}
&-horizontal &-item,
&-horizontal &-submenu {
margin-top: -1px;
@ -129,18 +124,12 @@
background-color: @item-active-bg;
}
&-horizontal,
&-inline,
&-vertical {
z-index: auto;
}
&-inline,
&-vertical {
border-right: @border-width-base @border-style-base @border-color-split;
&-vertical,
&-vertical-left,
&-vertical-right {
.@{menu-prefix-cls}-item {
position: relative;
z-index: 1;
&:after {
content: "";
position: absolute;
@ -155,7 +144,18 @@
}
}
&-vertical&-sub {
&-inline,
&-vertical,
&-vertical-left {
border-right: @border-width-base @border-style-base @border-color-split;
}
&-vertical-right {
border-left: @border-width-base @border-style-base @border-color-split;
}
&-vertical&-sub,
&-vertical-left&-sub,
&-vertical-right&-sub {
border-right: 0;
.@{menu-prefix-cls}-item {
border-right: 0;
@ -167,26 +167,11 @@
}
}
&-submenu-horizontal > & {
top: 100%;
left: 0;
position: absolute;
min-width: 100%;
margin-top: 7px;
z-index: @zindex-dropdown;
}
&-submenu-vertical {
z-index: 1;
}
&-submenu-vertical > & {
top: 0;
left: 100%;
position: absolute;
&-horizontal&-sub,
&-vertical&-sub,
&-vertical-left&-sub,
&-vertical-right&-sub {
min-width: 160px;
margin-left: 4px;
z-index: @zindex-dropdown;
}
&-item,
@ -217,7 +202,9 @@
}
&-submenu {
position: relative;
&-popup {
position: absolute;
}
> .@{menu-prefix-cls} {
background-color: @component-background;
@ -227,9 +214,11 @@
}
}
&-vertical > .@{menu-prefix-cls}-submenu-title,
&-inline > .@{menu-prefix-cls}-submenu-title {
.@{menu-prefix-cls}-submenu-arrow {
&-vertical,
&-vertical-left,
&-vertical-right,
&-inline {
> .@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow {
transition: transform .3s @ease-in-out;
position: absolute;
top: 50%;
@ -251,11 +240,19 @@
}
}
&-vertical > .@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow:before {
transform: rotate(-45deg) translateY(2px);
&-vertical,
&-vertical-left,
&-vertical-right {
> .@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow:before {
transform: rotate(-45deg) translateY(2px);
}
}
&-vertical > .@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow:after {
transform: rotate(45deg) translateY(-2px);
&-vertical,
&-vertical-left,
&-vertical-right {
> .@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow:after {
transform: rotate(45deg) translateY(-2px);
}
}
&-inline > .@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow:after {
@ -265,9 +262,11 @@
transform: rotate(-45deg) translateX(2px);
}
&-vertical > .@{menu-prefix-cls}-submenu-title:hover,
&-inline > .@{menu-prefix-cls}-submenu-title:hover {
.@{menu-prefix-cls}-submenu-arrow {
&-vertical,
&-vertical-left,
&-vertical-right,
&-inline {
> .@{menu-prefix-cls}-submenu-title:hover .@{menu-prefix-cls}-submenu-arrow {
&:after,
&:before {
background: linear-gradient(to right, @primary-color, @primary-color);
@ -288,7 +287,9 @@
}
}
&-vertical &-submenu-selected {
&-vertical &-submenu-selected,
&-vertical-left &-submenu-selected,
&-vertical-right &-submenu-selected {
color: @primary-color;
> a {
color: @primary-color;
@ -299,7 +300,6 @@
border: 0;
border-bottom: @border-width-base @border-style-base @border-color-split;
box-shadow: none;
z-index: 0;
line-height: 46px;
> .@{menu-prefix-cls}-item,
@ -335,6 +335,8 @@
}
&-vertical,
&-vertical-left,
&-vertical-right,
&-inline {
.@{menu-prefix-cls}-item,
.@{menu-prefix-cls}-submenu-title {
@ -344,7 +346,6 @@
height: @menu-item-height;
margin-top: 4px;
margin-bottom: 4px;
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
@ -423,7 +424,9 @@
}
}
&-vertical&-sub {
&-vertical&-sub,
&-vertical-left&-sub,
&-vertical-right&-sub {
padding: 0;
transform-origin: 0 0;
& > .@{menu-prefix-cls}-item,
@ -433,6 +436,8 @@
}
&-root&-vertical,
&-root&-vertical-left,
&-root&-vertical-right,
&-root&-inline {
box-shadow: none;
}
@ -511,12 +516,16 @@
}
&-dark&-inline,
&-dark&-vertical {
&-dark&-vertical,
&-dark&-vertical-left,
&-dark&-vertical-right {
border-right: 0;
}
&-dark&-inline &-item,
&-dark&-vertical &-item {
&-dark&-vertical &-item,
&-dark&-vertical-left &-item,
&-dark&-vertical-right &-item {
border-right: 0;
margin-left: 0;
left: 0;

@ -2,6 +2,8 @@ import React from 'react';
import { mount } from 'enzyme';
import Modal from '..';
jest.mock('rc-util/lib/Portal');
class ModalTester extends React.Component {
constructor(props) {
super(props);

@ -2,67 +2,66 @@
exports[`Modal render correctly 1`] = `
<div>
<div />
<div>
<div>
<div
class="ant-modal-mask fade-appear"
/>
<div
class="ant-modal-wrap "
role="dialog"
tabindex="-1"
>
<div
class="ant-modal-mask fade-appear"
/>
<div
class="ant-modal-wrap "
role="dialog"
tabindex="-1"
class="ant-modal zoom-appear"
role="document"
style="width: 520px;"
>
<div
class="ant-modal zoom-appear"
role="document"
style="width: 520px;"
class="ant-modal-content"
>
<button
aria-label="Close"
class="ant-modal-close"
>
<span
class="ant-modal-close-x"
/>
</button>
<div
class="ant-modal-content"
class="ant-modal-body"
>
<button
aria-label="Close"
class="ant-modal-close"
>
<span
class="ant-modal-close-x"
/>
</button>
<div
class="ant-modal-body"
>
Here is content of Modal
</div>
<div
class="ant-modal-footer"
>
<div>
<button
class="ant-btn"
type="button"
>
<span>
Cancel
</span>
</button>
<button
class="ant-btn ant-btn-primary"
type="button"
>
<span>
OK
</span>
</button>
</div>
</div>
Here is content of Modal
</div>
<div
style="width: 0px; height: 0px; overflow: hidden;"
tabindex="0"
class="ant-modal-footer"
>
sentinel
<div>
<button
class="ant-btn"
type="button"
>
<span>
Cancel
</span>
</button>
<button
class="ant-btn ant-btn-primary"
type="button"
>
<span>
OK
</span>
</button>
</div>
</div>
</div>
<div
style="width: 0px; height: 0px; overflow: hidden;"
tabindex="0"
>
sentinel
</div>
</div>
</div>
</div>
@ -71,45 +70,44 @@ exports[`Modal render correctly 1`] = `
exports[`Modal render without footer 1`] = `
<div>
<div />
<div>
<div>
<div
class="ant-modal-mask fade-appear"
/>
<div
class="ant-modal-wrap "
role="dialog"
tabindex="-1"
>
<div
class="ant-modal-mask fade-appear"
/>
<div
class="ant-modal-wrap "
role="dialog"
tabindex="-1"
class="ant-modal zoom-appear"
role="document"
style="width: 520px;"
>
<div
class="ant-modal zoom-appear"
role="document"
style="width: 520px;"
class="ant-modal-content"
>
<div
class="ant-modal-content"
<button
aria-label="Close"
class="ant-modal-close"
>
<button
aria-label="Close"
class="ant-modal-close"
>
<span
class="ant-modal-close-x"
/>
</button>
<div
class="ant-modal-body"
>
Here is content of Modal
</div>
</div>
<span
class="ant-modal-close-x"
/>
</button>
<div
style="width: 0px; height: 0px; overflow: hidden;"
tabindex="0"
class="ant-modal-body"
>
sentinel
Here is content of Modal
</div>
</div>
<div
style="width: 0px; height: 0px; overflow: hidden;"
tabindex="0"
>
sentinel
</div>
</div>
</div>
</div>

@ -7,6 +7,7 @@ describe('Modal.confirm triggers callbacks correctly', () => {
afterEach(() => {
errorSpy.mockReset();
document.body.innerHTML = '';
});
afterAll(() => {
@ -46,7 +47,7 @@ describe('Modal.confirm triggers callbacks correctly', () => {
onOk,
});
// second Modal
$$('.ant-btn-primary')[1].click();
$$('.ant-btn-primary')[0].click();
expect(onCancel.mock.calls.length).toBe(0);
expect(onOk.mock.calls.length).toBe(1);
});
@ -54,14 +55,14 @@ describe('Modal.confirm triggers callbacks correctly', () => {
it('should allow Modal.comfirm without onCancel been set', () => {
open();
// Third Modal
$$('.ant-btn')[4].click();
$$('.ant-btn')[0].click();
expect(errorSpy).not.toHaveBeenCalled();
});
it('should allow Modal.comfirm without onOk been set', () => {
open();
// Fourth Modal
$$('.ant-btn-primary')[3].click();
$$('.ant-btn-primary')[0].click();
expect(errorSpy).not.toHaveBeenCalled();
});
});

@ -22,7 +22,7 @@ describe('Popconfirm', () => {
const triggerNode = wrapper.find('span').at(0);
triggerNode.simulate('click');
expect(onVisibleChange).toBeCalledWith(true);
expect(document.querySelectorAll('.popconfirm-test').length).toBe(1);
expect(wrapper.find('.popconfirm-test').length).toBe(1);
triggerNode.simulate('click');
expect(onVisibleChange).toBeCalledWith(false);

@ -102,7 +102,7 @@ exports[`renders ./components/select/demo/basic.md correctly 1`] = `
</div>
<span
class="ant-select-selection__clear"
style="user-select:none;-webkit-user-select:none;display:block"
style="user-select:none;-webkit-user-select:none"
unselectable="unselectable"
/>
<span

@ -24,6 +24,7 @@ Select component to select value from options.
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| allowClear | Show clear button. | boolean | false |
| autoFocus | Get focus by default | boolean | false |
| combobox | Enable combobox mode (can not set multiple at the same time). (Deprecated after 2.9, use `mode` instead) | boolean | false |
| defaultActiveFirstOption | Whether active first option by default | boolean | true |
| defaultValue | Initial selected option. | string\|string\[] | - |
@ -35,6 +36,8 @@ Select component to select value from options.
| firstActiveValue | Value of action option by default | string\|string\[] | - |
| getPopupContainer | Parent Node which the selector should be rendered to. Default to `body`. When position issues happen, try to modify it into scrollable content and position it relative.[example](http://codepen.io/anon/pen/xVBOVQ?editors=001) | function(triggerNode) | () => document.body |
| labelInValue | whether to embed label in value, turn the format of value from `string` to `{key: string, label: ReactNode}` | boolean | false |
| maxTagCount | Max tag count to show | number | - |
| maxTagPlaceholder | Placeholder for not showing tags | ReactNode | - |
| mode | Set mode of Select (Support after 2.9) | 'multiple' \| 'tags' \| 'combobox' | - |
| multiple | Allow multiple select (Deprecated after 2.9, use `mode` instead) | boolean | false |
| notFoundContent | Specify content to show when no result matches.. | string | 'Not Found' |
@ -50,9 +53,18 @@ Select component to select value from options.
| onChange | Called when select an option or input value change, or value of input is changed in combobox mode | function(value, label) | - |
| onDeselect | Called when a option is deselected, the params are option's value (or key) . only called for multiple or tags, effective in multiple or tags mode only. | function(value) | - |
| onFocus | Called when focus | function | - |
| onMouseEnter | Called when mouse enter | function | - |
| onMouseLeave | Called when mouse leave | function | - |
| onSearch | Callback function that is fired when input changed. | function(value: string) | |
| onSelect | Called when a option is selected, the params are option's value (or key) and option instance. | function(value, option) | - |
### Select Methods
| Name | Description |
| --- | --- |
| blur() | Remove focus |
| focus() | Get focus |
### Option props
| Property | Description | Type | Default |

@ -52,6 +52,7 @@ export interface SelectProps extends AbstractSelectProps {
getPopupContainer?: (triggerNode: Element) => HTMLElement;
tokenSeparators?: string[];
getInputElement?: () => React.ReactElement<any>;
autoFocus?: boolean;
}
export interface OptionProps {
@ -93,6 +94,20 @@ export default class Select extends React.Component<SelectProps, any> {
static propTypes = SelectPropTypes;
private rcSelect: any;
focus() {
this.rcSelect.focus();
}
blur() {
this.rcSelect.blur();
}
saveSelect = (node) => {
this.rcSelect = node;
}
renderSelect = (locale) => {
const {
prefixCls,
@ -133,6 +148,7 @@ export default class Select extends React.Component<SelectProps, any> {
className={cls}
optionLabelProp={optionLabelProp || 'children'}
notFoundContent={notFoundContentLocale}
ref={this.saveSelect}
/>
);
}

@ -25,6 +25,7 @@ title: Select
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| allowClear | 支持清除 | boolean | false |
| autoFocus | 默认获取焦点 | boolean | false |
| combobox | 输入框自动提示模式2.9 之后废弃,请使用 `mode` | boolean | false |
| defaultActiveFirstOption | 是否默认高亮第一个选项。 | boolean | true |
| defaultValue | 指定默认选中的条目 | string\|string\[] | - |
@ -36,6 +37,8 @@ title: Select
| firstActiveValue | 默认高亮的选项 | string\|string\[] | - |
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | Function(triggerNode) | () => document.body |
| labelInValue | 是否把每个选项的 label 包装到 value 中,会把 Select 的 value 类型从 `string` 变为 `{key: string, label: ReactNode}` 的格式 | boolean | false |
| maxTagCount | 最多显示多少个 tag | number | - |
| maxTagPlaceholder | 隐藏 tag 时显示的内容 | ReactNode | - |
| mode | 设置 Select 的模式2.9 之后支持) | 'multiple' \| 'tags' \| 'combobox' | - |
| multiple | 支持多选2.9 之后废弃,请使用 `mode` | boolean | false |
| notFoundContent | 当下拉列表为空时显示的内容 | string | 'Not Found' |
@ -51,11 +54,20 @@ title: Select
| onChange | 选中 option或 input 的 value 变化combobox 模式下)时,调用此函数 | function(value) | - |
| onDeselect | 取消选中时调用,参数为选中项的 value (或 key) 值,仅在 multiple 或 tags 模式下生效 | function(value) | - |
| onFocus | 获得焦点时回调 | function | - |
| onMouseEnter | 鼠标移入时回调 | function | - |
| onMouseLeave | 鼠标移出时回调 | function | - |
| onSearch | 文本框值变化时回调 | function(value: string) | |
| onSelect | 被选中时调用,参数为选中项的 value (或 key) 值 | function(value, option) | - |
> 注意,如果发现下拉菜单跟随页面滚动,或者需要在其他弹层中触发 Select请尝试使用 `getPopupContainer={triggerNode => triggerNode.parentNode}` 将下拉弹层渲染节点固定在触发器的父元素中。
### Select Methods
| 名称 | 说明 |
| --- | --- |
| blur() | 取消焦点 |
| focus() | 获取焦点 |
### Option props
| 参数 | 说明 | 类型 | 默认值 |

@ -115,7 +115,7 @@ describe('Table.filter', () => {
}],
}));
wrapper.find('Dropdown').first().simulate('click');
wrapper.find('.ant-dropdown-trigger').first().simulate('click');
expect(handleChange).toBeCalledWith(true);
});

@ -133,7 +133,7 @@ exports[`Table.filter renders menu correctly 1`] = `
>
<ul
aria-activedescendant=""
class="ant-dropdown-menu ant-dropdown-menu-vertical ant-dropdown-menu-root"
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical"
role="menu"
tabindex="0"
>
@ -186,7 +186,7 @@ exports[`Table.filter renders menu correctly 1`] = `
</span>
</li>
<li
class="ant-dropdown-menu-submenu-vertical ant-dropdown-menu-submenu"
class="ant-dropdown-menu-submenu ant-dropdown-menu-submenu-vertical"
>
<div
aria-expanded="false"
@ -231,7 +231,7 @@ exports[`Table.filter renders radio filter correctly 1`] = `
>
<ul
aria-activedescendant=""
class="ant-dropdown-menu ant-dropdown-menu-vertical ant-dropdown-menu-root"
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical"
role="menu"
tabindex="0"
>
@ -284,7 +284,7 @@ exports[`Table.filter renders radio filter correctly 1`] = `
</span>
</li>
<li
class="ant-dropdown-menu-submenu-vertical ant-dropdown-menu-submenu"
class="ant-dropdown-menu-submenu ant-dropdown-menu-submenu-vertical"
>
<div
aria-expanded="false"

@ -7,7 +7,7 @@ exports[`Table.rowSelection render with default selection correctly 1`] = `
>
<ul
aria-activedescendant=""
class="ant-dropdown-menu ant-dropdown-menu-vertical ant-table-selection-menu ant-dropdown-menu-light ant-dropdown-menu-root"
class="ant-dropdown-menu ant-table-selection-menu ant-dropdown-menu-light ant-dropdown-menu-root ant-dropdown-menu-vertical"
role="menu"
tabindex="0"
>

@ -0,0 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Tooltip should hide when mouse leave antd disabled Button 1`] = `
<span
style="display: inline-block; cursor: not-allowed;"
>
<button
class="ant-btn"
disabled=""
style="pointer-events: none;"
type="button"
>
<span>
Hello world!
</span>
</button>
</span>
`;

@ -14,12 +14,12 @@ describe('Tooltip', () => {
mouseLeaveDelay={0}
onVisibleChange={onVisibleChange}
>
<div>Hello world!</div>
<div id="hello">Hello world!</div>
</Tooltip>
);
// `title` is empty.
const div = wrapper.find('div').at(0);
const div = wrapper.find('#hello').at(0);
div.simulate('mouseenter');
expect(onVisibleChange).not.toHaveBeenCalled();
expect(wrapper.instance().tooltip.props.visible).toBe(false);
@ -30,17 +30,17 @@ describe('Tooltip', () => {
// update `title` value.
wrapper.setProps({ title: 'Have a nice day!' });
wrapper.simulate('mouseenter');
wrapper.find('#hello').simulate('mouseenter');
expect(onVisibleChange).toHaveBeenLastCalledWith(true);
expect(wrapper.instance().tooltip.props.visible).toBe(true);
wrapper.simulate('mouseleave');
wrapper.find('#hello').simulate('mouseleave');
expect(onVisibleChange).toHaveBeenLastCalledWith(false);
expect(wrapper.instance().tooltip.props.visible).toBe(false);
// add `visible` props.
wrapper.setProps({ visible: false });
wrapper.simulate('mouseenter');
wrapper.find('#hello').simulate('mouseenter');
expect(onVisibleChange).toHaveBeenLastCalledWith(true);
const lastCount = onVisibleChange.mock.calls.length;
expect(wrapper.instance().tooltip.props.visible).toBe(false);
@ -88,7 +88,7 @@ describe('Tooltip', () => {
</Tooltip>
);
expect(wrapper.getDOMNode().tagName).toBe('SPAN');
expect(wrapper.render()).toMatchSnapshot();
const button = wrapper.find('span').at(0);
button.simulate('mouseenter');
expect(onVisibleChange).toBeCalledWith(true);
@ -110,8 +110,8 @@ describe('Tooltip', () => {
<Button disabled style={{ display: 'block' }}>Hello world!</Button>
</Tooltip>
);
expect(wrapper1.getDOMNode().style.display).toBe('inline-block');
expect(wrapper2.getDOMNode().style.display).toBe('block');
expect(wrapper1.find('span').first().getDOMNode().style.display).toBe('inline-block');
expect(wrapper2.find('span').first().getDOMNode().style.display).toBe('block');
});
it('should not wrap span when trigger is not hover', () => {
@ -134,38 +134,42 @@ describe('Tooltip', () => {
const horizontalArrowShift = 16;
const triggerWidth = 200;
const wrapper = mount(
<Tooltip
title="xxxxx"
trigger="click"
mouseEnterDelay={0}
mouseLeaveDelay={0}
placement="bottomLeft"
>
<button style={{ width: triggerWidth }}>
Hello world!
</button>
</Tooltip>
);
wrapper.find('button').at(0).simulate('click');
const popupLeftDefault = parseInt(wrapper.instance().getPopupDomNode().style.left, 10);
const wrapper2 = mount(
<Tooltip
title="xxxxx"
trigger="click"
mouseEnterDelay={0}
mouseLeaveDelay={0}
placement="bottomLeft"
arrowPointAtCenter
>
<button style={{ width: triggerWidth }}>
Hello world!
</button>
</Tooltip>
);
wrapper2.find('button').at(0).simulate('click');
const popupLeftArrowPointAtCenter = parseInt(wrapper2.instance().getPopupDomNode().style.left, 10);
expect(popupLeftArrowPointAtCenter - popupLeftDefault).toBe((triggerWidth / 2) - horizontalArrowShift - arrowWidth);
const suit = () => {
const wrapper = mount(
<Tooltip
title="xxxxx"
trigger="click"
mouseEnterDelay={0}
mouseLeaveDelay={0}
placement="bottomLeft"
>
<button style={{ width: triggerWidth }}>
Hello world!
</button>
</Tooltip>
);
wrapper.find('button').at(0).simulate('click');
const popupLeftDefault = parseInt(wrapper.instance().getPopupDomNode().style.left, 10);
const wrapper2 = mount(
<Tooltip
title="xxxxx"
trigger="click"
mouseEnterDelay={0}
mouseLeaveDelay={0}
placement="bottomLeft"
arrowPointAtCenter
>
<button style={{ width: triggerWidth }}>
Hello world!
</button>
</Tooltip>
);
wrapper2.find('button').at(0).simulate('click');
const popupLeftArrowPointAtCenter = parseInt(wrapper2.instance().getPopupDomNode().style.left, 10);
expect(popupLeftArrowPointAtCenter - popupLeftDefault).toBe((triggerWidth / 2) - horizontalArrowShift - arrowWidth);
};
jest.dontMock('rc-trigger', suit);
});
});

@ -15,7 +15,7 @@ A simple text popup tip.
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| title | The text shown in the tooltip | string\|React.Element | - |
| title | The text shown in the tooltip | string\|ReactNode\|() => ReactNode | - |
### Common API

@ -33,9 +33,11 @@ export interface AbstractTooltipProps {
children?: React.ReactNode;
}
export type RenderFunction = () => React.ReactNode;
export interface TooltipProps extends AbstractTooltipProps {
title?: React.ReactNode;
overlay?: React.ReactNode;
title?: React.ReactNode | RenderFunction;
overlay?: React.ReactNode | RenderFunction;
}
const splitObject = (obj, keys) => {

@ -17,7 +17,7 @@ title: Tooltip
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| title | 提示文字 | React.ReactNode | 无 |
| title | 提示文字 | string\|ReactNode\|() => ReactNode | 无 |
### 共同的 API

@ -50,30 +50,30 @@
"omit.js": "^1.0.0",
"prop-types": "^15.5.7",
"rc-animate": "^2.4.1",
"rc-calendar": "~9.1.0",
"rc-cascader": "~0.11.3",
"rc-calendar": "~9.2.0",
"rc-cascader": "~0.12.0",
"rc-checkbox": "~2.0.3",
"rc-collapse": "~1.7.5",
"rc-dialog": "~6.5.10",
"rc-dropdown": "~1.5.0",
"rc-dialog": "~7.0.0",
"rc-dropdown": "~2.1.0",
"rc-editor-mention": "^1.0.2",
"rc-form": "~1.5.0",
"rc-input-number": "~3.6.0",
"rc-menu": "~5.1.0",
"rc-menu": "~6.1.0",
"rc-notification": "~3.0.0",
"rc-pagination": "~1.12.4",
"rc-progress": "~2.2.2",
"rc-rate": "~2.1.1",
"rc-select": "~6.9.0",
"rc-slider": "~8.3.0",
"rc-select": "~7.1.0",
"rc-slider": "~8.4.0",
"rc-steps": "~3.0.0",
"rc-switch": "~1.5.1",
"rc-table": "~5.6.9",
"rc-tabs": "~9.1.2",
"rc-time-picker": "~3.0.0",
"rc-tooltip": "~3.4.6",
"rc-time-picker": "~3.1.0",
"rc-tooltip": "~3.7.0",
"rc-tree": "~1.7.0",
"rc-tree-select": "~1.10.2",
"rc-tree-select": "~1.11.0",
"rc-upload": "~2.4.0",
"rc-util": "^4.0.4",
"react-lazy-load": "^3.0.12",

@ -18,7 +18,6 @@
&:target {
border: 1px solid @primary-color;
z-index: 10;
}
&-expand-trigger {

@ -0,0 +1,31 @@
import React from 'react';
let Trigger; // eslint-disable-line
if (process.env.REACT === '15') {
const ActualTrigger = require.requireActual('rc-trigger');
const render = ActualTrigger.prototype.render;
ActualTrigger.prototype.render = function () {
const { popupVisible } = this.state;
let component;
if (popupVisible || this._component) { // eslint-disable-line
component = this.getComponent();
}
return (
<div id="TriggerContainer">
{render.call(this)}
{component}
</div>
);
};
Trigger = ActualTrigger;
} else {
const TriggerMock = require('rc-trigger/lib/mock'); // eslint-disable-line
Trigger = TriggerMock;
}
export default Trigger;

@ -0,0 +1,19 @@
import React from 'react';
export default class Portal extends React.Component {
componentDidMount() {
this.createContainer();
}
createContainer() {
this.container = true;
this.forceUpdate();
}
render() {
if (this.container) {
return this.props.children;
}
return null;
}
}
Loading…
Cancel
Save