chore: improve UX of RangePicker (#6200)

* chore: improve UX of RangePicker

* test: fix CI
This commit is contained in:
Benjy Cui 2017-05-22 09:42:04 +08:00 committed by GitHub
parent be238c7887
commit 1dae0b65f2
4 changed files with 49 additions and 9 deletions

View File

@ -33,7 +33,7 @@ function pickerValueAdapter(value?: moment.Moment | moment.Moment[]): moment.Mom
export default class RangePicker extends React.Component<any, any> {
static contextTypes = {
antLocale: PropTypes.object,
antLocale: PropTypes.object,
};
static defaultProps = {
prefixCls: 'ant-calendar',
@ -56,6 +56,7 @@ export default class RangePicker extends React.Component<any, any> {
this.state = {
value,
open: props.open,
hoverValue: [],
};
}
@ -78,6 +79,8 @@ export default class RangePicker extends React.Component<any, any> {
this.handleChange([]);
}
clearHoverValue = () => this.setState({ hoverValue: [] });
handleChange = (value: moment.Moment[]) => {
const props = this.props;
if (!('value' in props)) {
@ -100,6 +103,8 @@ export default class RangePicker extends React.Component<any, any> {
handleShowDateChange = showDate => this.setState({ showDate });
handleHoverChange = hoverValue => this.setState({ hoverValue });
setValue(value) {
this.handleChange(value);
if (!this.props.showTime) {
@ -115,7 +120,16 @@ export default class RangePicker extends React.Component<any, any> {
const operations = Object.keys(ranges).map((range) => {
const value = ranges[range];
return <a key={range} onClick={() => this.setValue(value)}>{range}</a>;
return (
<a
key={range}
onClick={() => this.setValue(value)}
onMouseEnter={() => this.setState({ hoverValue: value })}
onMouseLeave={this.clearHoverValue}
>
{range}
</a>
);
});
return (
<div className={`${prefixCls}-range-quick-selector`}>
@ -126,7 +140,7 @@ export default class RangePicker extends React.Component<any, any> {
render() {
const { state, props, context } = this;
const { value, showDate, open } = state;
const { value, showDate, hoverValue, open } = state;
const localeCode = getLocaleCode(context);
if (value && localeCode) {
if (value[0]) {
@ -138,9 +152,10 @@ export default class RangePicker extends React.Component<any, any> {
}
const {
disabledDate, disabledTime, showTime, showToday,
ranges, prefixCls, popupStyle,
style, onOk, locale, format,
prefixCls, popupStyle, style,
disabledDate, disabledTime,
showTime, showToday,
ranges, onOk, locale, format,
} = props;
warning(!('onOK' in props), 'It should be `RangePicker[onOk]`, instead of `onOK`!');
@ -182,6 +197,8 @@ export default class RangePicker extends React.Component<any, any> {
onOk={onOk}
value={showDate || pickerValueAdapter(props.defaultPickerValue) || pickerValueAdapter(moment())}
onValueChange={this.handleShowDateChange}
hoverValue={hoverValue}
onHoverChange={this.handleHoverChange}
showToday={showToday}
/>
);

View File

@ -41,6 +41,25 @@ describe('RangePicker', () => {
.toMatchSnapshot();
});
it('highlight range when hover presetted range', () => {
const wrapper = mount(
<RangePicker
ranges={{
'This Month': [moment(), moment().endOf('month')],
}}
getCalendarContainer={trigger => trigger}
format="YYYY/MM/DD"
open
/>
);
let rangeCalendarWrapper = mount(wrapper.find('Trigger').node.getComponent());
rangeCalendarWrapper.find('.ant-calendar-range-quick-selector a')
.simulate('mouseEnter');
rangeCalendarWrapper = mount(wrapper.find('Trigger').node.getComponent());
expect(rangeCalendarWrapper.find('.ant-calendar-selected-day').length).toBe(2);
});
// issue: https://github.com/ant-design/ant-design/issues/5872
it('should not throw error when value is reset to `[]`', () => {
const birthday = moment('2000-01-01', 'YYYY-MM-DD');

View File

@ -65,11 +65,13 @@ describe('RangePicker with showTime', () => {
<RangePicker showTime open onChange={onChangeFn} onOpenChange={onOpenChangeFn} />
);
const calendarWrapper = mount(wrapper.find('Trigger').node.getComponent());
let calendarWrapper = mount(wrapper.find('Trigger').node.getComponent());
expect(calendarWrapper.find('.ant-calendar-time-picker-btn').hasClass('ant-calendar-time-picker-btn-disabled')).toBe(true);
expect(calendarWrapper.find('.ant-calendar-ok-btn').hasClass('ant-calendar-ok-btn-disabled')).toBe(true);
calendarWrapper.find('.ant-calendar-date').at(10).simulate('click');
calendarWrapper = mount(wrapper.find('Trigger').node.getComponent()); // !!! TODO: calendarWrapper cannot get the latest state from wrapper
calendarWrapper.find('.ant-calendar-date').at(11).simulate('click');
calendarWrapper = mount(wrapper.find('Trigger').node.getComponent()); // !!!
expect(calendarWrapper.find('.ant-calendar-time-picker-btn').hasClass('ant-calendar-time-picker-btn-disabled')).toBe(false);
expect(calendarWrapper.find('.ant-calendar-ok-btn').hasClass('ant-calendar-ok-btn-disabled')).toBe(false);
expect(onChangeFn).toHaveBeenCalled();
@ -84,9 +86,11 @@ describe('RangePicker with showTime', () => {
<RangePicker showTime open onOk={onOkFn} onChange={onChangeFn} onOpenChange={onOpenChangeFn} />
);
const calendarWrapper = mount(wrapper.find('Trigger').node.getComponent());
let calendarWrapper = mount(wrapper.find('Trigger').node.getComponent());
calendarWrapper.find('.ant-calendar-date').at(10).simulate('click');
calendarWrapper = mount(wrapper.find('Trigger').node.getComponent()); // !!!
calendarWrapper.find('.ant-calendar-date').at(11).simulate('click');
calendarWrapper = mount(wrapper.find('Trigger').node.getComponent()); // !!!
onChangeFn.mockClear();
calendarWrapper.find('.ant-calendar-ok-btn').simulate('click');
expect(onOkFn).toHaveBeenCalled();

View File

@ -45,7 +45,7 @@
"omit.js": "^0.1.0",
"prop-types": "^15.5.7",
"rc-animate": "~2.3.0",
"rc-calendar": "~8.2.0",
"rc-calendar": "~8.3.0",
"rc-cascader": "~0.11.0",
"rc-checkbox": "~2.0.0",
"rc-collapse": "~1.7.0",