mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-02 20:19:44 +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;
|
||||
}
|
||||
|
||||
// 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 = {
|
||||
href: string;
|
||||
target?: string;
|
||||
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
onClick?: React.MouseEventHandler<any>;
|
||||
} & BaseButtonProps &
|
||||
Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'type'>;
|
||||
Omit<React.AnchorHTMLAttributes<any>, 'type'>;
|
||||
|
||||
export type NativeButtonProps = {
|
||||
htmlType?: ButtonHTMLType;
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
onClick?: React.MouseEventHandler<any>;
|
||||
} & BaseButtonProps &
|
||||
Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'type'>;
|
||||
Omit<React.ButtonHTMLAttributes<any>, 'type'>;
|
||||
|
||||
export type ButtonProps = AnchorButtonProps | NativeButtonProps;
|
||||
export type ButtonProps = Partial<AnchorButtonProps & NativeButtonProps>;
|
||||
|
||||
interface ButtonState {
|
||||
loading?: boolean | { delay?: number };
|
||||
|
@ -7,6 +7,8 @@ import { selectDate, openPanel, clearInput, nextYear, nextMonth, hasSelected } f
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
|
||||
describe('DatePicker', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
focusTest(DatePicker);
|
||||
|
||||
beforeEach(() => {
|
||||
@ -15,6 +17,11 @@ describe('DatePicker', () => {
|
||||
|
||||
afterEach(() => {
|
||||
MockDate.reset();
|
||||
errorSpy.mockReset();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('support name prop', () => {
|
||||
@ -210,4 +217,22 @@ describe('DatePicker', () => {
|
||||
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');
|
||||
});
|
||||
|
||||
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 { polyfill } from 'react-lifecycles-compat';
|
||||
import TimePickerPanel from 'rc-time-picker/lib/Panel';
|
||||
import classNames from 'classnames';
|
||||
import * as moment from 'moment';
|
||||
import enUS from './locale/en_US';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import { generateShowHourMinuteSecond } from '../time-picker';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
|
||||
type PickerType = 'date' | 'week' | 'month';
|
||||
|
||||
@ -43,8 +46,21 @@ function getColumns({ showHour, showMinute, showSecond, use12Hours }: any) {
|
||||
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 {
|
||||
return class PickerWrapper extends React.Component<any, any> {
|
||||
class PickerWrapper extends React.Component<any, any> {
|
||||
static defaultProps = {
|
||||
transitionName: 'slide-up',
|
||||
popupStyle: {},
|
||||
@ -54,6 +70,15 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, pickerType
|
||||
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;
|
||||
|
||||
componentDidMount() {
|
||||
@ -199,5 +224,8 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, pickerType
|
||||
</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
|
||||
// https://github.com/ant-design/ant-design/issues/7351
|
||||
onLabelClick = (e: any) => {
|
||||
const { label } = this.props;
|
||||
onLabelClick = () => {
|
||||
const id = this.props.id || this.getId();
|
||||
if (!id) {
|
||||
return;
|
||||
@ -313,17 +312,8 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
|
||||
const formItemNode = ReactDOM.findDOMNode(this) as Element;
|
||||
const control = formItemNode.querySelector(`[id="${id}"]`) as HTMLElement;
|
||||
|
||||
if (control) {
|
||||
// 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();
|
||||
}
|
||||
if (control && control.focus) {
|
||||
control.focus();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -9,10 +9,6 @@ Semantic vector graphics.
|
||||
|
||||
## List of icons
|
||||
|
||||
> Click the icon and copy the code.
|
||||
|
||||
We are still adding two-tone icons right now.
|
||||
|
||||
```__react
|
||||
import IconDisplay from 'site/theme/template/IconDisplay';
|
||||
ReactDOM.render(<IconDisplay />, mountNode);
|
||||
|
@ -14,10 +14,6 @@ toc: false
|
||||
|
||||
## 图标列表
|
||||
|
||||
> 点击图标即可复制代码。
|
||||
|
||||
新版图标可能略有缺失,我们还在持续补充中。
|
||||
|
||||
```__react
|
||||
import IconDisplay from 'site/theme/template/IconDisplay';
|
||||
ReactDOM.render(<IconDisplay />, mountNode);
|
||||
|
@ -218,8 +218,14 @@
|
||||
position: absolute;
|
||||
width: 6px;
|
||||
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-item-color} \9';
|
||||
background-image: linear-gradient(to right, @menu-item-color, @menu-item-color);
|
||||
background-image: ~'none \9';
|
||||
|
||||
border-radius: 2px;
|
||||
transition: background 0.3s @ease-in-out, transform 0.3s @ease-in-out,
|
||||
top 0.3s @ease-in-out;
|
||||
|
@ -18,6 +18,9 @@
|
||||
"contributors": [
|
||||
"ant"
|
||||
],
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"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-tips': ', or switch version with the select at header navigation.',
|
||||
'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.filled': 'Filled',
|
||||
'app.docs.components.icon.two-tone': 'Two Tone',
|
||||
|
@ -18,11 +18,6 @@ interface IconDisplayState {
|
||||
}
|
||||
|
||||
class IconDisplay extends React.Component<IconDisplayProps, IconDisplayState> {
|
||||
constructor(props: IconDisplayProps) {
|
||||
super(props);
|
||||
this.handleSearchIcon = debounce(this.handleSearchIcon, 300);
|
||||
}
|
||||
|
||||
static categories: Categories = categories;
|
||||
|
||||
static newIconNames: string[] = [];
|
||||
@ -38,6 +33,11 @@ class IconDisplay extends React.Component<IconDisplayProps, IconDisplayState> {
|
||||
searchKey: '',
|
||||
};
|
||||
|
||||
constructor(props: IconDisplayProps) {
|
||||
super(props);
|
||||
this.handleSearchIcon = debounce(this.handleSearchIcon, 300);
|
||||
}
|
||||
|
||||
getComputedDisplayList() {
|
||||
return Object.keys(IconDisplay.categories)
|
||||
.map((category: CategoriesKeys) => ({
|
||||
@ -89,8 +89,7 @@ class IconDisplay extends React.Component<IconDisplayProps, IconDisplayState> {
|
||||
} = this.props;
|
||||
const list = this.getComputedDisplayList();
|
||||
return (
|
||||
<div>
|
||||
<h3>{messages['app.docs.components.icon.pick-theme']}</h3>
|
||||
<>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<Radio.Group value={this.state.theme} onChange={this.handleChangeTheme} size="large">
|
||||
<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']}
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
|
||||
<Input.Search
|
||||
placeholder="icon name"
|
||||
placeholder={messages['app.docs.components.icon.search.placeholder']}
|
||||
style={{ marginLeft: 10, flex: 1 }}
|
||||
allowClear
|
||||
onChange={e => this.handleSearchIcon(e.currentTarget.value)}
|
||||
size="large"
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
|
||||
{this.renderCategories(list)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ module.exports = {
|
||||
'app.publish.old-version-guide': '如果您还需要使用旧版,请查阅 ',
|
||||
'app.publish.old-version-tips': ',也可通过页面右上角的文档版本选择框进行切换。',
|
||||
'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.filled': '实底风格',
|
||||
'app.docs.components.icon.two-tone': '双色风格',
|
||||
|
Loading…
Reference in New Issue
Block a user