mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 22:36:31 +08:00
Merge pull request #15638 from ant-design/master
Merge master to feature
This commit is contained in:
commit
e752ec3414
@ -1,8 +1,11 @@
|
||||
import raf from 'raf';
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import delayRaf from '../raf';
|
||||
import throttleByAnimationFrame from '../throttleByAnimationFrame';
|
||||
import getDataOrAriaProps from '../getDataOrAriaProps';
|
||||
import triggerEvent from '../triggerEvent';
|
||||
import Wave from '../wave';
|
||||
|
||||
describe('Test utils function', () => {
|
||||
beforeAll(() => {
|
||||
@ -128,4 +131,33 @@ describe('Test utils function', () => {
|
||||
triggerEvent(button, 'click');
|
||||
expect(button.style.width).toBe('100px');
|
||||
});
|
||||
|
||||
describe('wave', () => {
|
||||
it('bindAnimationEvent should return when node is null', () => {
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button" disabled />
|
||||
</Wave>,
|
||||
).instance();
|
||||
expect(wrapper.bindAnimationEvent()).toBe(undefined);
|
||||
});
|
||||
|
||||
it('bindAnimationEvent.onClick should return when children is hidden', () => {
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<button type="button" style={{ display: 'none' }} />
|
||||
</Wave>,
|
||||
).instance();
|
||||
expect(wrapper.bindAnimationEvent()).toBe(undefined);
|
||||
});
|
||||
|
||||
it('bindAnimationEvent.onClick should return when children is input', () => {
|
||||
const wrapper = mount(
|
||||
<Wave>
|
||||
<input />
|
||||
</Wave>,
|
||||
).instance();
|
||||
expect(wrapper.bindAnimationEvent()).toBe(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -127,4 +127,14 @@ describe('Affix Render', () => {
|
||||
jest.runAllTimers();
|
||||
expect(wrapper.instance().affix.state.affixStyle.top).toBe(10);
|
||||
});
|
||||
|
||||
it('updatePosition when target changed', () => {
|
||||
const container = '<div id="mounter" />';
|
||||
const getTarget = () => container;
|
||||
wrapper = mount(<Affix target={getTarget} />);
|
||||
wrapper.setProps({ target: null });
|
||||
expect(wrapper.instance().state.status).toBe(0);
|
||||
expect(wrapper.instance().state.affixStyle).toBe(undefined);
|
||||
expect(wrapper.instance().state.placeholderStyle).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
@ -147,7 +147,7 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
type === 'month'
|
||||
? this.getMonthSelectElement(prefixCls, value.month(), this.getMonthsLocale(value))
|
||||
: null;
|
||||
const size = (fullscreen ? 'default' : 'small') as any;
|
||||
const size = fullscreen ? 'default' : 'small';
|
||||
const typeSwitch = (
|
||||
<Group onChange={this.onTypeChange} value={type} size={size}>
|
||||
<Button value="month">{locale.month}</Button>
|
||||
|
@ -3,6 +3,7 @@ import Moment from 'moment';
|
||||
import { mount } from 'enzyme';
|
||||
import MockDate from 'mockdate';
|
||||
import Calendar from '..';
|
||||
import Header from '../Header';
|
||||
|
||||
describe('Calendar', () => {
|
||||
it('Calendar should be selectable', () => {
|
||||
@ -175,4 +176,84 @@ describe('Calendar', () => {
|
||||
expect(onPanelChange).toBeCalled();
|
||||
expect(onPanelChange.mock.calls[0][1]).toEqual('year');
|
||||
});
|
||||
|
||||
const createWrapper = (start, end, value, onValueChange) => {
|
||||
const wrapper = mount(
|
||||
<Header
|
||||
onValueChange={onValueChange}
|
||||
value={value}
|
||||
validRange={[start, end]}
|
||||
locale={{ year: '年' }}
|
||||
/>,
|
||||
);
|
||||
wrapper
|
||||
.find('.ant-fullcalendar-year-select')
|
||||
.hostNodes()
|
||||
.simulate('click');
|
||||
wrapper
|
||||
.find('.ant-select-dropdown-menu-item')
|
||||
.at(0)
|
||||
.simulate('click');
|
||||
};
|
||||
|
||||
it('if value.month > end.month, set value.month to end.month', () => {
|
||||
const value = new Moment('1990-01-03');
|
||||
const start = new Moment('2019-04-01');
|
||||
const end = new Moment('2019-11-01');
|
||||
const onValueChange = jest.fn();
|
||||
createWrapper(start, end, value, onValueChange);
|
||||
expect(onValueChange).toHaveBeenCalledWith(value.year('2019').month('3'));
|
||||
});
|
||||
|
||||
it('if start.month > value.month, set value.month to start.month ', () => {
|
||||
const value = new Moment('1990-01-03');
|
||||
const start = new Moment('2019-11-01');
|
||||
const end = new Moment('2019-03-01');
|
||||
const onValueChange = jest.fn();
|
||||
createWrapper(start, end, value, onValueChange);
|
||||
expect(onValueChange).toHaveBeenCalledWith(value.year('2019').month('10'));
|
||||
});
|
||||
|
||||
it('onMonthChange should work correctly', () => {
|
||||
const start = new Moment('2018-11-01');
|
||||
const end = new Moment('2019-03-01');
|
||||
const value = new Moment('2018-12-03');
|
||||
const onValueChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Header
|
||||
onValueChange={onValueChange}
|
||||
value={value}
|
||||
validRange={[start, end]}
|
||||
locale={{ year: '年' }}
|
||||
type="month"
|
||||
/>,
|
||||
);
|
||||
wrapper
|
||||
.find('.ant-fullcalendar-month-select')
|
||||
.hostNodes()
|
||||
.simulate('click');
|
||||
wrapper
|
||||
.find('.ant-select-dropdown-menu-item')
|
||||
.at(0)
|
||||
.simulate('click');
|
||||
expect(onValueChange).toHaveBeenCalledWith(value.month(10));
|
||||
});
|
||||
|
||||
it('onTypeChange should work correctly', () => {
|
||||
const onTypeChange = jest.fn();
|
||||
const value = new Moment('2018-12-03');
|
||||
const wrapper = mount(
|
||||
<Header
|
||||
onTypeChange={onTypeChange}
|
||||
locale={{ year: '年', month: '月' }}
|
||||
value={value}
|
||||
type="date"
|
||||
/>,
|
||||
);
|
||||
wrapper
|
||||
.find('input')
|
||||
.at(1)
|
||||
.simulate('change');
|
||||
expect(onTypeChange).toBeCalledWith('year');
|
||||
});
|
||||
});
|
||||
|
@ -55,4 +55,62 @@ describe('Card', () => {
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('warning', () => {
|
||||
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
mount(<Card noHovering>xxx</Card>);
|
||||
expect(warnSpy).toBeCalledWith(
|
||||
'Warning: [antd: Card] `noHovering` is deprecated, you can remove it safely or use `hoverable` instead.',
|
||||
);
|
||||
mount(<Card noHovering={false}>xxx</Card>);
|
||||
expect(warnSpy).toBeCalledWith(
|
||||
'Warning: [antd: Card] `noHovering={false}` is deprecated, use `hoverable` instead.',
|
||||
);
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('unmount', () => {
|
||||
const wrapper = mount(<Card>xxx</Card>);
|
||||
const removeResizeEventSpy = jest.spyOn(wrapper.instance().resizeEvent, 'remove');
|
||||
wrapper.unmount();
|
||||
expect(removeResizeEventSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onTabChange should work', () => {
|
||||
const tabList = [
|
||||
{
|
||||
key: 'tab1',
|
||||
tab: 'tab1',
|
||||
},
|
||||
{
|
||||
key: 'tab2',
|
||||
tab: 'tab2',
|
||||
},
|
||||
];
|
||||
const onTabChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Card onTabChange={onTabChange} tabList={tabList}>
|
||||
xxx
|
||||
</Card>,
|
||||
);
|
||||
wrapper
|
||||
.find('.ant-tabs-tab')
|
||||
.at(1)
|
||||
.simulate('click');
|
||||
expect(onTabChange).toBeCalledWith('tab2');
|
||||
});
|
||||
|
||||
it('getCompatibleHoverable should work', () => {
|
||||
const wrapper = mount(<Card noHovering={false}>xxx</Card>);
|
||||
expect(wrapper.find('.ant-card-hoverable').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should not render when actions is number', () => {
|
||||
const wrapper = mount(
|
||||
<Card title="Card title" actions={11}>
|
||||
<p>Card content</p>
|
||||
</Card>,
|
||||
);
|
||||
expect(wrapper.find('.ant-card-actions').length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
@ -129,9 +129,6 @@ export default class Card extends React.Component<CardProps, CardState> {
|
||||
}
|
||||
|
||||
getAction(actions: React.ReactNode[]) {
|
||||
if (!actions || !actions.length) {
|
||||
return null;
|
||||
}
|
||||
const actionList = actions.map((action, index) => (
|
||||
<li style={{ width: `${100 / actions.length}%` }} key={`action-${index}`}>
|
||||
<span>{action}</span>
|
||||
|
@ -230,6 +230,7 @@
|
||||
}
|
||||
|
||||
&-disabled-cell &-date {
|
||||
position: relative;
|
||||
width: auto;
|
||||
color: @disabled-color;
|
||||
background: @disabled-bg;
|
||||
@ -241,6 +242,18 @@
|
||||
background: @disabled-bg;
|
||||
}
|
||||
}
|
||||
|
||||
&-disabled-cell&-selected-day &-date::before {
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: 5px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: @border-radius-sm;
|
||||
content: '';
|
||||
}
|
||||
|
||||
&-disabled-cell&-today &-date {
|
||||
position: relative;
|
||||
padding-right: 5px;
|
||||
|
@ -348,9 +348,6 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
labelAlign === 'left' && `${labelClsBasic}-left`,
|
||||
mergedLabelCol.className,
|
||||
);
|
||||
const labelClassName = classNames({
|
||||
[`${prefixCls}-item-required`]: required,
|
||||
});
|
||||
|
||||
let labelChildren = label;
|
||||
// Keep label is original where there should have no colon
|
||||
@ -361,6 +358,11 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
labelChildren = (label as string).replace(/[:|:]\s*$/, '');
|
||||
}
|
||||
|
||||
const labelClassName = classNames({
|
||||
[`${prefixCls}-item-required`]: required,
|
||||
[`${prefixCls}-item-no-colon`]: !computedColon,
|
||||
});
|
||||
|
||||
return label ? (
|
||||
<Col {...mergedLabelCol} className={labelColClassName}>
|
||||
<label
|
||||
@ -395,28 +397,19 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
}
|
||||
|
||||
renderFormItem = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, style, className } = this.props;
|
||||
const prefixCls = getPrefixCls('form', customizePrefixCls);
|
||||
const children = this.renderChildren(prefixCls);
|
||||
const itemClassName = {
|
||||
[`${prefixCls}-item`]: true,
|
||||
[`${prefixCls}-item-with-help`]: this.helpShow,
|
||||
[`${className}`]: !!className,
|
||||
};
|
||||
|
||||
return (
|
||||
<FormContext.Consumer key="row">
|
||||
{({ colon: contextColon }: FormContextProps) => {
|
||||
const { prefixCls: customizePrefixCls, style, colon, className } = this.props;
|
||||
|
||||
const computedColon = colon === true || (contextColon !== false && colon !== false);
|
||||
|
||||
const prefixCls = getPrefixCls('form', customizePrefixCls);
|
||||
const children = this.renderChildren(prefixCls);
|
||||
const itemClassName = {
|
||||
[`${prefixCls}-item`]: true,
|
||||
[`${prefixCls}-item-with-help`]: this.helpShow,
|
||||
[`${prefixCls}-item-no-colon`]: !computedColon,
|
||||
[`${className}`]: !!className,
|
||||
};
|
||||
return (
|
||||
<Row className={classNames(itemClassName)} style={style}>
|
||||
{children}
|
||||
</Row>
|
||||
);
|
||||
}}
|
||||
</FormContext.Consumer>
|
||||
<Row className={classNames(itemClassName)} style={style} key="row">
|
||||
{children}
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -2121,7 +2121,7 @@ exports[`renders ./components/form/demo/style-check-debug.md correctly 1`] = `
|
||||
class="ant-form-item-label"
|
||||
>
|
||||
<label
|
||||
class=""
|
||||
class="ant-form-item-no-colon"
|
||||
title="input:64.5px"
|
||||
>
|
||||
input:64.5px
|
||||
|
@ -5,13 +5,13 @@ exports[`Form should props colon of Form.Item override the props colon of Form.
|
||||
class="ant-form ant-form-horizontal"
|
||||
>
|
||||
<div
|
||||
class="ant-row ant-form-item ant-form-item-no-colon"
|
||||
class="ant-row ant-form-item"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-label"
|
||||
>
|
||||
<label
|
||||
class=""
|
||||
class="ant-form-item-no-colon"
|
||||
title="label"
|
||||
>
|
||||
label
|
||||
@ -59,13 +59,13 @@ exports[`Form should props colon of Form.Item override the props colon of Form.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-row ant-form-item ant-form-item-no-colon"
|
||||
class="ant-row ant-form-item"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-label"
|
||||
>
|
||||
<label
|
||||
class=""
|
||||
class="ant-form-item-no-colon"
|
||||
title="label"
|
||||
>
|
||||
label
|
||||
|
@ -31,6 +31,7 @@ describe('Form', () => {
|
||||
<Form.Item label="label:">input</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('.ant-form-item-label label')
|
||||
@ -48,12 +49,12 @@ describe('Form', () => {
|
||||
it('should disable colon when props colon Form is false', () => {
|
||||
const wrapper = mount(
|
||||
<Form colon={false}>
|
||||
<Form.Item>input</Form.Item>
|
||||
<Form.Item label="label">input</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
expect(
|
||||
wrapper
|
||||
.find('.ant-form-item')
|
||||
.find('.ant-form-item-label label')
|
||||
.at(0)
|
||||
.hasClass('ant-form-item-no-colon'),
|
||||
).toBe(true);
|
||||
|
@ -74,7 +74,7 @@ class App extends React.Component {
|
||||
<Form layout="horizontal" onSubmit={this.handleSubmit}>
|
||||
<Row>
|
||||
<Col span={span}>
|
||||
<Item {...itemLayout} label="测试字段">
|
||||
<Item colon={false} {...itemLayout} label="测试字段">
|
||||
{getFieldDecorator("item1", {
|
||||
rules: [{ required: true, message: "请必须填写此字段" }],
|
||||
})(<Input />)}
|
||||
@ -121,7 +121,7 @@ class App extends React.Component {
|
||||
<Form>
|
||||
<Row gutter={16}>
|
||||
<Col {...ColSpan}>
|
||||
<Item label="input:64.5px">
|
||||
<Item colon={false} label="input:64.5px">
|
||||
<Input />
|
||||
</Item>
|
||||
</Col>
|
||||
|
@ -232,6 +232,10 @@ interface UserFormProps extends FormComponentProps {
|
||||
class UserForm extends React.Component<UserFormProps, any> {
|
||||
// ...
|
||||
}
|
||||
|
||||
const App = Form.create<UserFormProps>({
|
||||
// ...
|
||||
})(UserForm);
|
||||
```
|
||||
|
||||
<style>
|
||||
|
@ -234,6 +234,10 @@ interface UserFormProps extends FormComponentProps {
|
||||
class UserForm extends React.Component<UserFormProps, any> {
|
||||
// ...
|
||||
}
|
||||
|
||||
const App = Form.create<UserFormProps>({
|
||||
// ...
|
||||
})(UserForm);
|
||||
```
|
||||
|
||||
<style>
|
||||
|
@ -35,6 +35,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-item-label > label {
|
||||
color: @label-color;
|
||||
|
||||
&::after {
|
||||
& when (@form-item-trailing-colon=true) {
|
||||
content: ':';
|
||||
}
|
||||
& when not (@form-item-trailing-colon=true) {
|
||||
content: ' ';
|
||||
}
|
||||
|
||||
position: relative;
|
||||
top: -0.5px;
|
||||
margin: 0 8px 0 2px;
|
||||
}
|
||||
|
||||
&.@{form-prefix-cls}-item-no-colon::after {
|
||||
content: ' ';
|
||||
}
|
||||
}
|
||||
|
||||
// Radio && Checkbox
|
||||
input[type='radio'],
|
||||
input[type='checkbox'] {
|
||||
@ -105,31 +126,11 @@ input[type='checkbox'] {
|
||||
&-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
> label {
|
||||
color: @label-color;
|
||||
|
||||
&::after {
|
||||
& when (@form-item-trailing-colon=true) {
|
||||
content: ':';
|
||||
}
|
||||
& when not (@form-item-trailing-colon=true) {
|
||||
content: ' ';
|
||||
}
|
||||
position: relative;
|
||||
top: -0.5px;
|
||||
margin: 0 8px 0 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{ant-prefix}-switch {
|
||||
margin: 2px 0 4px;
|
||||
}
|
||||
|
||||
&-no-colon &-label label::after {
|
||||
content: ' ';
|
||||
}
|
||||
}
|
||||
|
||||
.@{form-prefix-cls}-explain,
|
||||
|
@ -5,7 +5,7 @@ import Icon from '../icon';
|
||||
|
||||
export interface PasswordProps extends InputProps {
|
||||
readonly inputPrefixCls?: string;
|
||||
readonly action: string;
|
||||
readonly action?: string;
|
||||
visibilityToggle?: boolean;
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
|
||||
|
||||
getIcon() {
|
||||
const { prefixCls, action } = this.props;
|
||||
const iconTrigger = ActionMap[action] || '';
|
||||
const iconTrigger = ActionMap[action!] || '';
|
||||
const iconProps = {
|
||||
[iconTrigger]: this.onChange,
|
||||
className: `${prefixCls}-icon`,
|
||||
|
@ -113,4 +113,18 @@ describe('Mention', () => {
|
||||
expect(items.length).toBe(1);
|
||||
expect(items.at(0).props().children).toBe('bamboo');
|
||||
});
|
||||
|
||||
it('check filteredSuggestions', () => {
|
||||
if (process.env.REACT === '15') {
|
||||
return;
|
||||
}
|
||||
const wrapper = mount(<Mention defaultSuggestions={[<Mention.Nav value="light" />]} />);
|
||||
wrapper.find('DraftEditorContents').simulate('focus');
|
||||
const ed = wrapper.find('.public-DraftEditor-content');
|
||||
ed.simulate('beforeInput', { data: '@l' });
|
||||
jest.runAllTimers();
|
||||
const items = wrapper.find('div.ant-mention-dropdown-item');
|
||||
expect(items.length).toBe(1);
|
||||
expect(items.at(0).props().value).toBe('light');
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { Item } from 'rc-menu';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import Tooltip from '../tooltip';
|
||||
import { ClickParam } from './index';
|
||||
|
||||
@ -17,29 +16,22 @@ export interface MenuItemProps {
|
||||
onMouseLeave?: (e: { key: string; domEvent: MouseEvent }) => void;
|
||||
}
|
||||
|
||||
class MenuItem extends React.Component<MenuItemProps, any> {
|
||||
static contextTypes = {
|
||||
inlineCollapsed: PropTypes.bool,
|
||||
};
|
||||
class MenuItem extends React.Component<MenuItemProps> {
|
||||
static isMenuItem = 1;
|
||||
context: any;
|
||||
private menuItem: any;
|
||||
private menuItem: this;
|
||||
|
||||
onKeyDown = (e: React.MouseEvent<HTMLElement>) => {
|
||||
this.menuItem.onKeyDown(e);
|
||||
};
|
||||
saveMenuItem = (menuItem: any) => {
|
||||
saveMenuItem = (menuItem: this) => {
|
||||
this.menuItem = menuItem;
|
||||
};
|
||||
render() {
|
||||
const { inlineCollapsed } = this.context;
|
||||
const { level, children, rootPrefixCls } = this.props;
|
||||
const { title, ...rest } = this.props;
|
||||
|
||||
let titleNode;
|
||||
if (inlineCollapsed) {
|
||||
titleNode = title || (level === 1 ? children : '');
|
||||
}
|
||||
titleNode = title || (level === 1 ? children : '');
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
@ -47,7 +39,7 @@ class MenuItem extends React.Component<MenuItemProps, any> {
|
||||
placement="right"
|
||||
overlayClassName={`${rootPrefixCls}-inline-collapsed-tooltip`}
|
||||
>
|
||||
<Item {...rest} title={inlineCollapsed ? null : title} ref={this.saveMenuItem} />
|
||||
<Item {...rest} title={title} ref={this.saveMenuItem} />
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
@ -537,4 +537,55 @@ describe('Menu', () => {
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-menu-submenu-popup').length).toBe(0);
|
||||
});
|
||||
|
||||
it('onMouseEnter should work', () => {
|
||||
const onMouseEnter = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Menu onMouseEnter={onMouseEnter} defaultSelectedKeys={['test1']}>
|
||||
<Menu.Item key="test1">Navigation One</Menu.Item>
|
||||
<Menu.Item key="test2">Navigation Two</Menu.Item>
|
||||
</Menu>,
|
||||
);
|
||||
wrapper
|
||||
.find('Menu')
|
||||
.at(1)
|
||||
.simulate('mouseenter');
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('get correct animation type when switched from inline', () => {
|
||||
const wrapper = mount(<Menu mode="inline" />);
|
||||
wrapper.setProps({ mode: 'horizontal' });
|
||||
expect(wrapper.instance().getMenuOpenAnimation('')).toBe('');
|
||||
expect(wrapper.instance().switchingModeFromInline).toBe(false);
|
||||
});
|
||||
|
||||
it('Menu should not shake when collapsed changed', () => {
|
||||
const wrapper = mount(
|
||||
<Menu
|
||||
defaultSelectedKeys={['5']}
|
||||
defaultOpenKeys={['sub1']}
|
||||
mode="inline"
|
||||
inlineCollapsed={false}
|
||||
>
|
||||
<SubMenu
|
||||
key="sub1"
|
||||
title={
|
||||
<span>
|
||||
<span>Navigation One</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item key="5">Option 5</Menu.Item>
|
||||
<Menu.Item key="6">Option 6</Menu.Item>
|
||||
</SubMenu>
|
||||
</Menu>,
|
||||
);
|
||||
expect(wrapper.instance().contextSiderCollapsed).toBe(true);
|
||||
wrapper.setProps({ inlineCollapsed: true });
|
||||
expect(wrapper.instance().contextSiderCollapsed).toBe(false);
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
expect(wrapper.instance().contextSiderCollapsed).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@ -189,6 +189,7 @@ class Menu extends React.Component<MenuProps, MenuState> {
|
||||
onClick(e);
|
||||
}
|
||||
};
|
||||
|
||||
handleOpenChange = (openKeys: string[]) => {
|
||||
this.setOpenKeys(openKeys);
|
||||
|
||||
@ -218,6 +219,9 @@ class Menu extends React.Component<MenuProps, MenuState> {
|
||||
if (this.context.siderCollapsed !== undefined) {
|
||||
return this.context.siderCollapsed;
|
||||
}
|
||||
if (this.contextSiderCollapsed) {
|
||||
return false;
|
||||
}
|
||||
return inlineCollapsed;
|
||||
}
|
||||
|
||||
|
@ -230,7 +230,7 @@ span.@{radio-prefix-cls} + * {
|
||||
&-checked {
|
||||
z-index: 1;
|
||||
color: @radio-dot-color;
|
||||
background: @radio-button-bg;
|
||||
background: @radio-button-checked-bg;
|
||||
border-color: @radio-dot-color;
|
||||
box-shadow: -1px 0 0 0 @radio-dot-color;
|
||||
&::before {
|
||||
|
@ -193,6 +193,7 @@
|
||||
|
||||
// Radio buttons
|
||||
@radio-button-bg: @btn-default-bg;
|
||||
@radio-button-checked-bg: @btn-default-bg;
|
||||
@radio-button-color: @btn-default-color;
|
||||
@radio-button-hover-color: @primary-5;
|
||||
@radio-button-active-color: @primary-7;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import demoTest from '../../../tests/shared/demoTest';
|
||||
|
||||
demoTest('table', {
|
||||
skip: process.env.REACT === '15' ? ['edit-row'] : [],
|
||||
skip: process.env.REACT === '15' ? ['edit-row', 'drag-sorting'] : [],
|
||||
});
|
||||
|
@ -370,4 +370,39 @@ describe('Upload', () => {
|
||||
);
|
||||
expect(typeof wrapper.instance().upload.abort).toBe('function');
|
||||
});
|
||||
|
||||
it('unmount', () => {
|
||||
const wrapper = mount(
|
||||
<Upload>
|
||||
<button type="button">upload</button>
|
||||
</Upload>,
|
||||
);
|
||||
const clearIntervalSpy = jest.spyOn(global, 'clearInterval');
|
||||
expect(clearIntervalSpy).not.toHaveBeenCalled();
|
||||
wrapper.unmount();
|
||||
expect(clearIntervalSpy).toHaveBeenCalled();
|
||||
clearIntervalSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('corrent dragCls when type is drag', () => {
|
||||
const fileList = [{ status: 'uploading', uid: 'file' }];
|
||||
const wrapper = mount(
|
||||
<Upload type="drag" fileList={fileList}>
|
||||
<button type="button">upload</button>
|
||||
</Upload>,
|
||||
);
|
||||
expect(wrapper.find('.ant-upload-drag-uploading').length).toBe(1);
|
||||
});
|
||||
|
||||
it('return when targetItem is null', () => {
|
||||
const fileList = [{ uid: 'file' }];
|
||||
const wrapper = mount(
|
||||
<Upload type="drag" fileList={fileList}>
|
||||
<button type="button">upload</button>
|
||||
</Upload>,
|
||||
).instance();
|
||||
expect(wrapper.onSuccess('', { uid: 'fileItem' })).toBe(undefined);
|
||||
expect(wrapper.onProgress('', { uid: 'fileItem' })).toBe(undefined);
|
||||
expect(wrapper.onError('', '', { uid: 'fileItem' })).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
@ -72,7 +72,7 @@
|
||||
}
|
||||
|
||||
&.@{upload-prefix-cls}-drag-hover:not(.@{upload-prefix-cls}-disabled) {
|
||||
border: 2px dashed @primary-5;
|
||||
border-color: @primary-7;
|
||||
}
|
||||
|
||||
&.@{upload-prefix-cls}-disabled {
|
||||
|
@ -44,7 +44,7 @@ Ant Design 通过网格体系来实现视觉体系的秩序。网格的基数为
|
||||
|
||||
## 关于栅格
|
||||
|
||||
Ant Design 采用 24 栅格体系。以 1440 上下布局的结构为例,对宽度为 1168 的内容区域 进行 24 栅格的划分设置,如下图所示。我们为页面中栅格的 Gutter 设定了定值,即浏览器在一定范围扩大或缩小,栅格的 Column 宽度会随之扩大或缩小,但 Gutter 的宽度值固定不变。
|
||||
Ant Design 采用 24 栅格体系。以上下布局的结构为例,对内容区域进行 24 栅格的划分设置,如下图所示。我们为页面中栅格的 Gutter 设定了定值,即浏览器在一定范围扩大或缩小,栅格的 Column 宽度会随之扩大或缩小,但 Gutter 的宽度值固定不变。
|
||||
|
||||
![栅格 layout](https://gw.alipayobjects.com/zos/rmsportal/YPUZpPCzFgQHVxXCIAzq.png)
|
||||
|
||||
|
@ -7,12 +7,20 @@ footer {
|
||||
z-index: 9;
|
||||
clear: both;
|
||||
margin-left: -1px;
|
||||
color: rgba(255, 255, 255, 0.65);
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
font-size: 14px;
|
||||
background-color: #000;
|
||||
|
||||
.ant-row {
|
||||
.footer-wrap {
|
||||
position: relative;
|
||||
padding: 86px @padding-space 93px @padding-space;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.25);
|
||||
|
||||
> .ant-row {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.footer-center {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
@ -36,14 +44,15 @@ footer {
|
||||
}
|
||||
> div {
|
||||
margin: 12px 0;
|
||||
|
||||
> span {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer-wrap {
|
||||
position: relative;
|
||||
padding: 86px @padding-space 93px @padding-space;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
margin: 0;
|
||||
padding: 16px @padding-space;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||
import { Modal, message, Row, Col, Badge, Icon } from 'antd';
|
||||
import { Modal, message, Row, Col, Icon } from 'antd';
|
||||
import { Link } from 'bisheng/router';
|
||||
import { isLocalStorageNameSupported, loadScript, getLocalizedPathname } from '../utils';
|
||||
import ColorPicker from '../Color/ColorPicker';
|
||||
@ -105,7 +105,7 @@ class Footer extends React.Component {
|
||||
return (
|
||||
<footer id="footer">
|
||||
<div className="footer-wrap">
|
||||
<Row>
|
||||
<Row gutter={16}>
|
||||
<Col md={6} sm={24} xs={24}>
|
||||
<div className="footer-center">
|
||||
<h2>
|
||||
@ -120,7 +120,7 @@ class Footer extends React.Component {
|
||||
<div>
|
||||
<a href="http://ng.ant.design">NG-ZORRO</a>
|
||||
<span> - </span>
|
||||
Ant Design of Angular
|
||||
<span>Ant Design of Angular</span>
|
||||
</div>
|
||||
<div>
|
||||
<a href="http://ng.mobile.ant.design">NG-ZORRO-MOBILE</a>
|
||||
@ -136,13 +136,11 @@ class Footer extends React.Component {
|
||||
<FormattedMessage id="app.footer.kitchen" />
|
||||
</div>
|
||||
<div>
|
||||
<Badge dot offset={[3, 0]}>
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://landing.ant.design">
|
||||
Ant Design Landing
|
||||
</a>
|
||||
<span> - </span>
|
||||
<FormattedMessage id="app.footer.landing" />
|
||||
</Badge>
|
||||
<a target="_blank" rel="noopener noreferrer" href="http://landing.ant.design">
|
||||
Ant Design Landing
|
||||
</a>
|
||||
<span> - </span>
|
||||
<FormattedMessage id="app.footer.landing" />
|
||||
</div>
|
||||
<div>
|
||||
<a href="http://scaffold.ant.design">Scaffolds</a>
|
||||
|
Loading…
Reference in New Issue
Block a user