mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-03 20:49:14 +08:00
Merge branch 'feature' into tree-select-showSearch
This commit is contained in:
commit
58768b90f6
1
.npmignore
Normal file
1
.npmignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
~*
|
@ -62,20 +62,23 @@ export interface BaseButtonProps {
|
|||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Typescript will make optional not optional if use Pick with union.
|
||||||
|
// Should change to `AnchorButtonProps | NativeButtonProps` and `any` to `HTMLAnchorElement | HTMLButtonElement` if it fixed.
|
||||||
|
// ref: https://github.com/ant-design/ant-design/issues/15930
|
||||||
export type AnchorButtonProps = {
|
export type AnchorButtonProps = {
|
||||||
href: string;
|
href: string;
|
||||||
target?: string;
|
target?: string;
|
||||||
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
onClick?: React.MouseEventHandler<any>;
|
||||||
} & BaseButtonProps &
|
} & BaseButtonProps &
|
||||||
Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'type'>;
|
Omit<React.AnchorHTMLAttributes<any>, 'type'>;
|
||||||
|
|
||||||
export type NativeButtonProps = {
|
export type NativeButtonProps = {
|
||||||
htmlType?: ButtonHTMLType;
|
htmlType?: ButtonHTMLType;
|
||||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
onClick?: React.MouseEventHandler<any>;
|
||||||
} & BaseButtonProps &
|
} & BaseButtonProps &
|
||||||
Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'type'>;
|
Omit<React.ButtonHTMLAttributes<any>, 'type'>;
|
||||||
|
|
||||||
export type ButtonProps = AnchorButtonProps | NativeButtonProps;
|
export type ButtonProps = Partial<AnchorButtonProps & NativeButtonProps>;
|
||||||
|
|
||||||
interface ButtonState {
|
interface ButtonState {
|
||||||
loading?: boolean | { delay?: number };
|
loading?: boolean | { delay?: number };
|
||||||
|
@ -7,6 +7,8 @@ import { selectDate, openPanel, clearInput, nextYear, nextMonth, hasSelected } f
|
|||||||
import focusTest from '../../../tests/shared/focusTest';
|
import focusTest from '../../../tests/shared/focusTest';
|
||||||
|
|
||||||
describe('DatePicker', () => {
|
describe('DatePicker', () => {
|
||||||
|
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||||
|
|
||||||
focusTest(DatePicker);
|
focusTest(DatePicker);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -15,6 +17,11 @@ describe('DatePicker', () => {
|
|||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
MockDate.reset();
|
MockDate.reset();
|
||||||
|
errorSpy.mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
errorSpy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('support name prop', () => {
|
it('support name prop', () => {
|
||||||
@ -210,4 +217,22 @@ describe('DatePicker', () => {
|
|||||||
wrapper.find('.ant-calendar-input').simulate('change', { target: { value: '02/07/18' } });
|
wrapper.find('.ant-calendar-input').simulate('change', { target: { value: '02/07/18' } });
|
||||||
expect(wrapper.find('.ant-calendar-picker-input').getDOMNode().value).toBe('02/07/2018');
|
expect(wrapper.find('.ant-calendar-picker-input').getDOMNode().value).toBe('02/07/2018');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('warning use if use invalidate moment', () => {
|
||||||
|
const invalidateTime = moment('I AM INVALIDATE');
|
||||||
|
|
||||||
|
it('defaultValue', () => {
|
||||||
|
mount(<DatePicker defaultValue={invalidateTime} />);
|
||||||
|
expect(errorSpy).toHaveBeenCalledWith(
|
||||||
|
'Warning: [antd: DatePicker] `defaultValue` provides invalidate moment time. If you want to set empty value, use `null` instead.',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('value', () => {
|
||||||
|
mount(<DatePicker value={invalidateTime} />);
|
||||||
|
expect(errorSpy).toHaveBeenCalledWith(
|
||||||
|
'Warning: [antd: DatePicker] `value` provides invalidate moment time. If you want to set empty value, use `null` instead.',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { polyfill } from 'react-lifecycles-compat';
|
||||||
import TimePickerPanel from 'rc-time-picker/lib/Panel';
|
import TimePickerPanel from 'rc-time-picker/lib/Panel';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import * as moment from 'moment';
|
||||||
import enUS from './locale/en_US';
|
import enUS from './locale/en_US';
|
||||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||||
import { generateShowHourMinuteSecond } from '../time-picker';
|
import { generateShowHourMinuteSecond } from '../time-picker';
|
||||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||||
|
import warning from '../_util/warning';
|
||||||
|
|
||||||
type PickerType = 'date' | 'week' | 'month';
|
type PickerType = 'date' | 'week' | 'month';
|
||||||
|
|
||||||
@ -43,8 +46,21 @@ function getColumns({ showHour, showMinute, showSecond, use12Hours }: any) {
|
|||||||
return column;
|
return column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkValidate(value: any, propName: string) {
|
||||||
|
const values: any[] = Array.isArray(value) ? value : [value];
|
||||||
|
values.forEach(val => {
|
||||||
|
if (!val) return;
|
||||||
|
|
||||||
|
warning(
|
||||||
|
!moment.isMoment(val) || val.isValid(),
|
||||||
|
'DatePicker',
|
||||||
|
`\`${propName}\` provides invalidate moment time. If you want to set empty value, use \`null\` instead.`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export default function wrapPicker(Picker: React.ComponentClass<any>, pickerType: PickerType): any {
|
export default function wrapPicker(Picker: React.ComponentClass<any>, pickerType: PickerType): any {
|
||||||
return class PickerWrapper extends React.Component<any, any> {
|
class PickerWrapper extends React.Component<any, any> {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
transitionName: 'slide-up',
|
transitionName: 'slide-up',
|
||||||
popupStyle: {},
|
popupStyle: {},
|
||||||
@ -54,6 +70,15 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, pickerType
|
|||||||
locale: {},
|
locale: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static getDerivedStateFromProps({ value, defaultValue }: any) {
|
||||||
|
checkValidate(defaultValue, 'defaultValue');
|
||||||
|
checkValidate(value, 'value');
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since we need call `getDerivedStateFromProps` for check. Need leave an empty `state` here.
|
||||||
|
state = {};
|
||||||
|
|
||||||
private picker: any;
|
private picker: any;
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -199,5 +224,8 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, pickerType
|
|||||||
</LocaleReceiver>
|
</LocaleReceiver>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
polyfill(PickerWrapper);
|
||||||
|
return PickerWrapper;
|
||||||
}
|
}
|
||||||
|
@ -304,8 +304,7 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
|||||||
|
|
||||||
// Resolve duplicated ids bug between different forms
|
// Resolve duplicated ids bug between different forms
|
||||||
// https://github.com/ant-design/ant-design/issues/7351
|
// https://github.com/ant-design/ant-design/issues/7351
|
||||||
onLabelClick = (e: any) => {
|
onLabelClick = () => {
|
||||||
const { label } = this.props;
|
|
||||||
const id = this.props.id || this.getId();
|
const id = this.props.id || this.getId();
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return;
|
return;
|
||||||
@ -313,17 +312,8 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
|||||||
|
|
||||||
const formItemNode = ReactDOM.findDOMNode(this) as Element;
|
const formItemNode = ReactDOM.findDOMNode(this) as Element;
|
||||||
const control = formItemNode.querySelector(`[id="${id}"]`) as HTMLElement;
|
const control = formItemNode.querySelector(`[id="${id}"]`) as HTMLElement;
|
||||||
|
if (control && control.focus) {
|
||||||
if (control) {
|
control.focus();
|
||||||
// Only prevent in default situation
|
|
||||||
// Avoid preventing event in `label={<a href="xx">link</a>}``
|
|
||||||
if (typeof label === 'string') {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (control.focus) {
|
|
||||||
control.focus();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,10 +9,6 @@ Semantic vector graphics.
|
|||||||
|
|
||||||
## List of icons
|
## List of icons
|
||||||
|
|
||||||
> Click the icon and copy the code.
|
|
||||||
|
|
||||||
We are still adding two-tone icons right now.
|
|
||||||
|
|
||||||
```__react
|
```__react
|
||||||
import IconDisplay from 'site/theme/template/IconDisplay';
|
import IconDisplay from 'site/theme/template/IconDisplay';
|
||||||
ReactDOM.render(<IconDisplay />, mountNode);
|
ReactDOM.render(<IconDisplay />, mountNode);
|
||||||
|
@ -14,10 +14,6 @@ toc: false
|
|||||||
|
|
||||||
## 图标列表
|
## 图标列表
|
||||||
|
|
||||||
> 点击图标即可复制代码。
|
|
||||||
|
|
||||||
新版图标可能略有缺失,我们还在持续补充中。
|
|
||||||
|
|
||||||
```__react
|
```__react
|
||||||
import IconDisplay from 'site/theme/template/IconDisplay';
|
import IconDisplay from 'site/theme/template/IconDisplay';
|
||||||
ReactDOM.render(<IconDisplay />, mountNode);
|
ReactDOM.render(<IconDisplay />, mountNode);
|
||||||
|
@ -218,8 +218,14 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
width: 6px;
|
width: 6px;
|
||||||
height: 1.5px;
|
height: 1.5px;
|
||||||
|
// background + background-image to makes before & after cross have same color.
|
||||||
|
// Since `linear-gradient` not work on IE9, we should hack it.
|
||||||
|
// ref: https://github.com/ant-design/ant-design/issues/15910
|
||||||
background: @menu-bg;
|
background: @menu-bg;
|
||||||
|
background: ~'@{menu-item-color} \9';
|
||||||
background-image: linear-gradient(to right, @menu-item-color, @menu-item-color);
|
background-image: linear-gradient(to right, @menu-item-color, @menu-item-color);
|
||||||
|
background-image: ~'none \9';
|
||||||
|
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
transition: background 0.3s @ease-in-out, transform 0.3s @ease-in-out,
|
transition: background 0.3s @ease-in-out, transform 0.3s @ease-in-out,
|
||||||
top 0.3s @ease-in-out;
|
top 0.3s @ease-in-out;
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
"contributors": [
|
"contributors": [
|
||||||
"ant"
|
"ant"
|
||||||
],
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npmjs.org/"
|
||||||
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ant-design/ant-design"
|
"url": "https://github.com/ant-design/ant-design"
|
||||||
|
@ -104,7 +104,7 @@ module.exports = {
|
|||||||
'app.publish.old-version-guide': 'If you need documentation of older version, please visit ',
|
'app.publish.old-version-guide': 'If you need documentation of older version, please visit ',
|
||||||
'app.publish.old-version-tips': ', or switch version with the select at header navigation.',
|
'app.publish.old-version-tips': ', or switch version with the select at header navigation.',
|
||||||
'app.docs.color.pick-primary': 'Pick your primary color',
|
'app.docs.color.pick-primary': 'Pick your primary color',
|
||||||
'app.docs.components.icon.pick-theme': 'Select the Icon Theme',
|
'app.docs.components.icon.search.placeholder': 'Search icon here, click icon to copy code',
|
||||||
'app.docs.components.icon.outlined': 'Outlined',
|
'app.docs.components.icon.outlined': 'Outlined',
|
||||||
'app.docs.components.icon.filled': 'Filled',
|
'app.docs.components.icon.filled': 'Filled',
|
||||||
'app.docs.components.icon.two-tone': 'Two Tone',
|
'app.docs.components.icon.two-tone': 'Two Tone',
|
||||||
|
@ -18,11 +18,6 @@ interface IconDisplayState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class IconDisplay extends React.Component<IconDisplayProps, IconDisplayState> {
|
class IconDisplay extends React.Component<IconDisplayProps, IconDisplayState> {
|
||||||
constructor(props: IconDisplayProps) {
|
|
||||||
super(props);
|
|
||||||
this.handleSearchIcon = debounce(this.handleSearchIcon, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
static categories: Categories = categories;
|
static categories: Categories = categories;
|
||||||
|
|
||||||
static newIconNames: string[] = [];
|
static newIconNames: string[] = [];
|
||||||
@ -38,6 +33,11 @@ class IconDisplay extends React.Component<IconDisplayProps, IconDisplayState> {
|
|||||||
searchKey: '',
|
searchKey: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constructor(props: IconDisplayProps) {
|
||||||
|
super(props);
|
||||||
|
this.handleSearchIcon = debounce(this.handleSearchIcon, 300);
|
||||||
|
}
|
||||||
|
|
||||||
getComputedDisplayList() {
|
getComputedDisplayList() {
|
||||||
return Object.keys(IconDisplay.categories)
|
return Object.keys(IconDisplay.categories)
|
||||||
.map((category: CategoriesKeys) => ({
|
.map((category: CategoriesKeys) => ({
|
||||||
@ -89,8 +89,7 @@ class IconDisplay extends React.Component<IconDisplayProps, IconDisplayState> {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
const list = this.getComputedDisplayList();
|
const list = this.getComputedDisplayList();
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<h3>{messages['app.docs.components.icon.pick-theme']}</h3>
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<Radio.Group value={this.state.theme} onChange={this.handleChangeTheme} size="large">
|
<Radio.Group value={this.state.theme} onChange={this.handleChangeTheme} size="large">
|
||||||
<Radio.Button value="outlined">
|
<Radio.Button value="outlined">
|
||||||
@ -103,18 +102,17 @@ class IconDisplay extends React.Component<IconDisplayProps, IconDisplayState> {
|
|||||||
<Icon component={TwoToneIcon} /> {messages['app.docs.components.icon.two-tone']}
|
<Icon component={TwoToneIcon} /> {messages['app.docs.components.icon.two-tone']}
|
||||||
</Radio.Button>
|
</Radio.Button>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
|
|
||||||
<Input.Search
|
<Input.Search
|
||||||
placeholder="icon name"
|
placeholder={messages['app.docs.components.icon.search.placeholder']}
|
||||||
style={{ marginLeft: 10, flex: 1 }}
|
style={{ marginLeft: 10, flex: 1 }}
|
||||||
allowClear
|
allowClear
|
||||||
onChange={e => this.handleSearchIcon(e.currentTarget.value)}
|
onChange={e => this.handleSearchIcon(e.currentTarget.value)}
|
||||||
size="large"
|
size="large"
|
||||||
|
autoFocus
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.renderCategories(list)}
|
{this.renderCategories(list)}
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ module.exports = {
|
|||||||
'app.publish.old-version-guide': '如果您还需要使用旧版,请查阅 ',
|
'app.publish.old-version-guide': '如果您还需要使用旧版,请查阅 ',
|
||||||
'app.publish.old-version-tips': ',也可通过页面右上角的文档版本选择框进行切换。',
|
'app.publish.old-version-tips': ',也可通过页面右上角的文档版本选择框进行切换。',
|
||||||
'app.docs.color.pick-primary': '选择你的主色',
|
'app.docs.color.pick-primary': '选择你的主色',
|
||||||
'app.docs.components.icon.pick-theme': '选择图标主题风格',
|
'app.docs.components.icon.search.placeholder': '在此搜索图标,点击图标可复制代码',
|
||||||
'app.docs.components.icon.outlined': '线框风格',
|
'app.docs.components.icon.outlined': '线框风格',
|
||||||
'app.docs.components.icon.filled': '实底风格',
|
'app.docs.components.icon.filled': '实底风格',
|
||||||
'app.docs.components.icon.two-tone': '双色风格',
|
'app.docs.components.icon.two-tone': '双色风格',
|
||||||
|
Loading…
Reference in New Issue
Block a user