Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: optimize hover value experience #139

Merged
merged 3 commits into from
Sep 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/RangePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -564,9 +564,9 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
const onDateMouseLeave = () => {
setHoverRangedValue(updateValues(selectedValue, null, mergedActivePickerIndex));
if (mergedActivePickerIndex === 0) {
onStartLeave(null);
onStartLeave();
} else {
onEndLeave(null);
onEndLeave();
}
};

Expand Down Expand Up @@ -1013,9 +1013,9 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
triggerChange(values, mergedActivePickerIndex);
// clear hover value style
if (mergedActivePickerIndex === 0) {
onStartLeave(null);
onStartLeave();
} else {
onEndLeave(null);
onEndLeave();
}
} else {
setSelectedValue(values);
Expand Down
26 changes: 20 additions & 6 deletions src/hooks/useHoverValue.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import { useState, useEffect } from 'react';
import { useState, useEffect, useRef } from 'react';
import useValueTexts, { ValueTextConfig } from './useValueTexts';

export default function useHoverValue<DateType>(
valueText: string,
{ formatList, generateConfig, locale }: ValueTextConfig<DateType>,
): [string, (date: DateType) => void, (date: DateType) => void] {
const [value, setValue] = useState(null);
): [string, (date: DateType) => void, (immediately?: boolean) => void] {
const [value, internalSetValue] = useState<DateType>(null);
const raf = useRef(null);

function setValue(val: DateType, immediately: boolean = false) {
cancelAnimationFrame(raf.current);
if (immediately) {
internalSetValue(val);
return;
}
raf.current = requestAnimationFrame(() => {
internalSetValue(val);
});
}

const [, firstText] = useValueTexts(value, {
formatList,
Expand All @@ -17,13 +29,15 @@ export default function useHoverValue<DateType>(
setValue(date);
}

function onLeave() {
setValue(null);
function onLeave(immediately: boolean = false) {
setValue(null, immediately);
}

useEffect(() => {
onLeave();
onLeave(true);
}, [valueText]);

useEffect(() => () => cancelAnimationFrame(raf.current), []);

return [firstText, onEnter, onLeave];
}
14 changes: 14 additions & 0 deletions tests/picker.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -740,14 +740,24 @@ describe('Picker.Basic', () => {
});

describe('hover value', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
it('should restore when leave', () => {
const wrapper = mount(<MomentPicker open defaultValue={getMoment('2020-07-22')} />);
const cell = wrapper.findCell(24);
cell.simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('input').prop('value')).toBe('2020-07-24');
expect(wrapper.find('.rc-picker-input').hasClass('rc-picker-input-placeholder')).toBeTruthy();

cell.simulate('mouseLeave');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('input').prop('value')).toBe('2020-07-22');
expect(wrapper.find('.rc-picker-input').hasClass('rc-picker-input-placeholder')).toBeFalsy();
});
Expand All @@ -757,6 +767,8 @@ describe('Picker.Basic', () => {
wrapper.openPicker();
const cell = wrapper.findCell(24);
cell.simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('input').prop('value')).toBe('2020-07-24');
expect(wrapper.find('.rc-picker-input').hasClass('rc-picker-input-placeholder')).toBeTruthy();

Expand All @@ -770,6 +782,8 @@ describe('Picker.Basic', () => {
wrapper.openPicker();
const cell = wrapper.findCell(24);
cell.simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('input').prop('value')).toBe('2020-07-24');
expect(wrapper.find('.rc-picker-input').hasClass('rc-picker-input-placeholder')).toBeTruthy();

Expand Down
67 changes: 43 additions & 24 deletions tests/range.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,13 @@ describe('Picker.Range', () => {
});

describe('hover placeholder', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});

const defaultValue: [Moment, Moment] = [getMoment('2020-07-22'), getMoment('2020-08-22')];

it('should restore when leave', () => {
Expand All @@ -1439,6 +1446,8 @@ describe('Picker.Range', () => {
wrapper.openPicker(0);
const leftCell = wrapper.findCell(24);
leftCell.simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
expect(
wrapper
.find('input')
Expand All @@ -1465,6 +1474,8 @@ describe('Picker.Range', () => {
).toBeFalsy();

leftCell.simulate('mouseLeave');
jest.runAllTimers();
wrapper.update();
expect(
wrapper
.find('input')
Expand Down Expand Up @@ -1496,6 +1507,8 @@ describe('Picker.Range', () => {
wrapper.openPicker(1);
const rightCell = wrapper.findCell(24, 1);
rightCell.simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
expect(
wrapper
.find('input')
Expand All @@ -1522,6 +1535,8 @@ describe('Picker.Range', () => {
).toBeTruthy();

rightCell.simulate('mouseLeave');
jest.runAllTimers();
wrapper.update();
expect(
wrapper
.find('input')
Expand Down Expand Up @@ -1556,6 +1571,8 @@ describe('Picker.Range', () => {
wrapper.openPicker(0);
const leftCell = wrapper.findCell(24, 0);
leftCell.simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
expect(
wrapper
.find('input')
Expand Down Expand Up @@ -1610,6 +1627,8 @@ describe('Picker.Range', () => {
// right
const rightCell = wrapper.findCell(24, 1);
rightCell.simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
expect(
wrapper
.find('input')
Expand Down Expand Up @@ -1661,6 +1680,30 @@ describe('Picker.Range', () => {
.hasClass('rc-picker-input-placeholder'),
).toBeFalsy();
});

// https://github.com/ant-design/ant-design/issues/26544
it('should clean hover style when selecting the same value with last value', () => {
const wrapper = mount(
<MomentRangePicker defaultValue={[getMoment('2020-07-24'), getMoment('2020-08-24')]} />,
);

wrapper.openPicker();

wrapper.selectCell(24, 0);
expect(
wrapper
.find('input')
.first()
.prop('value'),
).toBe('2020-07-24');
expect(
wrapper
.find('input')
.first()
.hasClass('rc-picker-input-placeholder'),
).toBeFalsy();
expect(wrapper.isOpen()).toBeTruthy();
});
});

// https://github.com/ant-design/ant-design/issues/25746
Expand Down Expand Up @@ -1699,30 +1742,6 @@ describe('Picker.Range', () => {
expect(wrapper.find('.rc-picker-ok button').props().disabled).toBeTruthy();
});

// https://github.com/ant-design/ant-design/issues/26544
it('should clean hover style when selecting the same value with last value', () => {
const wrapper = mount(
<MomentRangePicker defaultValue={[getMoment('2020-07-24'), getMoment('2020-08-24')]} />,
);

wrapper.openPicker();

wrapper.selectCell(24, 0);
expect(
wrapper
.find('input')
.first()
.prop('value'),
).toBe('2020-07-24');
expect(
wrapper
.find('input')
.first()
.hasClass('rc-picker-input-placeholder'),
).toBeFalsy();
expect(wrapper.isOpen()).toBeTruthy();
});

// https://github.com/ant-design/ant-design/issues/26024
it('panel should keep open when nextValue is empty', () => {
const wrapper = mount(<MomentRangePicker />);
Expand Down