Skip to content

Commit ca9e814

Browse files
authored
chore(hoverPlaceholder): optmize logic when value is not empty (#109)
* chore(hoverPlaceholder): optmize logic when value is not empty * refactor: useHoverPlaceholder to useHoverValue * test: add case for RangePicker * chore(hoverValue): optimize onChange for input
1 parent 90f32bd commit ca9e814

File tree

6 files changed

+282
-80
lines changed

6 files changed

+282
-80
lines changed

assets/index.less

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22

33
@background-color: rgb(255, 240, 255);
44

5+
@input-placeholder-color: hsv(0, 0, 75%);
6+
7+
.placeholder(@color: @input-placeholder-color) {
8+
// Firefox
9+
&::-moz-placeholder {
10+
opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526
11+
}
12+
13+
&::placeholder {
14+
color: @color;
15+
}
16+
17+
&:placeholder-shown {
18+
text-overflow: ellipsis;
19+
}
20+
}
21+
522
.@{prefix-cls} {
623
display: inline-flex;
724

@@ -292,6 +309,13 @@
292309

293310
> input {
294311
width: 100%;
312+
.placeholder();
313+
}
314+
315+
&-placeholder {
316+
> input {
317+
color: @input-placeholder-color;
318+
}
295319
}
296320
}
297321

src/Picker.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { getDefaultFormat, getInputSize, elementsContains } from './utils/uiUtil
3030
import usePickerInput from './hooks/usePickerInput';
3131
import useTextValueMapping from './hooks/useTextValueMapping';
3232
import useValueTexts from './hooks/useValueTexts';
33-
import useHoverPlaceholder from './hooks/useHoverPlaceholder';
33+
import useHoverValue from './hooks/useHoverValue';
3434

3535
export interface PickerRefConfig {
3636
focus: () => void;
@@ -436,7 +436,7 @@ function InnerPicker<DateType>(props: PickerProps<DateType>) {
436436
};
437437
const popupPlacement = direction === 'rtl' ? 'bottomRight' : 'bottomLeft';
438438

439-
const [hoverPlaceholder, onEnter, onLeave] = useHoverPlaceholder(placeholder, text, {
439+
const [hoverValue, onEnter, onLeave] = useHoverValue(text, {
440440
formatList,
441441
generateConfig,
442442
locale,
@@ -481,18 +481,23 @@ function InnerPicker<DateType>(props: PickerProps<DateType>) {
481481
onContextMenu={onContextMenu}
482482
onClick={onClick}
483483
>
484-
<div className={`${prefixCls}-input`} ref={inputDivRef}>
484+
<div
485+
className={classNames(`${prefixCls}-input`, {
486+
[`${prefixCls}-input-placeholder`]: !!hoverValue,
487+
})}
488+
ref={inputDivRef}
489+
>
485490
<input
486491
id={id}
487492
tabIndex={tabIndex}
488493
disabled={disabled}
489494
readOnly={inputReadOnly || !typing}
490-
value={text}
495+
value={hoverValue || text}
491496
onChange={e => {
492497
triggerTextChange(e.target.value);
493498
}}
494499
autoFocus={autoFocus}
495-
placeholder={hoverPlaceholder}
500+
placeholder={placeholder}
496501
ref={inputRef}
497502
title={text}
498503
{...inputProps}

src/RangePicker.tsx

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import getExtraFooter from './utils/getExtraFooter';
2929
import getRanges from './utils/getRanges';
3030
import useRangeViewDates from './hooks/useRangeViewDates';
3131
import { DateRender } from './panels/DatePanel/DateBody';
32-
import useHoverPlaceholder from './hooks/useHoverPlaceholder';
32+
import useHoverValue from './hooks/useHoverValue';
3333

3434
function reorderValues<DateType>(
3535
values: RangeValue<DateType>,
@@ -540,25 +540,17 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
540540
// ========================== Hover Range ==========================
541541
const [hoverRangedValue, setHoverRangedValue] = useState<RangeValue<DateType>>(null);
542542

543-
const [startPlaceholder, onStartEnter, onStartLeave] = useHoverPlaceholder(
544-
getValue(placeholder, 0) || '',
545-
startText,
546-
{
547-
formatList,
548-
generateConfig,
549-
locale,
550-
},
551-
);
543+
const [startHoverValue, onStartEnter, onStartLeave] = useHoverValue(startText, {
544+
formatList,
545+
generateConfig,
546+
locale,
547+
});
552548

553-
const [endPlaceholder, onEndEnter, onEndLeave] = useHoverPlaceholder(
554-
getValue(placeholder, 1) || '',
555-
endText,
556-
{
557-
formatList,
558-
generateConfig,
559-
locale,
560-
},
561-
);
549+
const [endHoverValue, onEndEnter, onEndLeave] = useHoverValue(endText, {
550+
formatList,
551+
generateConfig,
552+
locale,
553+
});
562554

563555
const onDateMouseEnter = (date: DateType) => {
564556
setHoverRangedValue(updateValues(selectedValue, date, mergedActivePickerIndex));
@@ -1062,19 +1054,20 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
10621054
<div
10631055
className={classNames(`${prefixCls}-input`, {
10641056
[`${prefixCls}-input-active`]: mergedActivePickerIndex === 0,
1057+
[`${prefixCls}-input-placeholder`]: !!startHoverValue,
10651058
})}
10661059
ref={startInputDivRef}
10671060
>
10681061
<input
10691062
id={id}
10701063
disabled={mergedDisabled[0]}
10711064
readOnly={inputReadOnly || !startTyping}
1072-
value={startText}
1065+
value={startHoverValue || startText}
10731066
onChange={e => {
10741067
triggerStartTextChange(e.target.value);
10751068
}}
10761069
autoFocus={autoFocus}
1077-
placeholder={startPlaceholder}
1070+
placeholder={getValue(placeholder, 0) || ''}
10781071
ref={startInputRef}
10791072
{...startInputProps}
10801073
{...inputSharedProps}
@@ -1087,17 +1080,18 @@ function InnerRangePicker<DateType>(props: RangePickerProps<DateType>) {
10871080
<div
10881081
className={classNames(`${prefixCls}-input`, {
10891082
[`${prefixCls}-input-active`]: mergedActivePickerIndex === 1,
1083+
[`${prefixCls}-input-placeholder`]: !!endHoverValue,
10901084
})}
10911085
ref={endInputDivRef}
10921086
>
10931087
<input
10941088
disabled={mergedDisabled[1]}
10951089
readOnly={inputReadOnly || !endTyping}
1096-
value={endText}
1090+
value={endHoverValue || endText}
10971091
onChange={e => {
10981092
triggerEndTextChange(e.target.value);
10991093
}}
1100-
placeholder={endPlaceholder}
1094+
placeholder={getValue(placeholder, 1) || ''}
11011095
ref={endInputRef}
11021096
{...endInputProps}
11031097
{...inputSharedProps}
Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
1-
import { useState } from 'react';
1+
import { useState, useEffect } from 'react';
22
import useValueTexts, { ValueTextConfig } from './useValueTexts';
33

4-
export default function useHoverPlaceholder<DateType>(
5-
placeholder: string,
6-
text: string,
4+
export default function useHoverValue<DateType>(
5+
valueText: string,
76
{ formatList, generateConfig, locale }: ValueTextConfig<DateType>,
87
): [string, (date: DateType) => void, (date: DateType) => void] {
98
const [value, setValue] = useState(null);
109

11-
const [valueTexts] = useValueTexts(value, {
10+
const [, firstText] = useValueTexts(value, {
1211
formatList,
1312
generateConfig,
1413
locale,
1514
});
1615

1716
function onEnter(date: DateType) {
18-
if (!text) {
19-
setValue(date);
20-
}
17+
setValue(date);
2118
}
2219

2320
function onLeave() {
2421
setValue(null);
2522
}
2623

27-
return [(valueTexts && valueTexts[0]) || placeholder, onEnter, onLeave];
24+
useEffect(() => {
25+
onLeave();
26+
}, [valueText]);
27+
28+
return [firstText, onEnter, onLeave];
2829
}

tests/picker.spec.tsx

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -730,33 +730,52 @@ describe('Picker.Basic', () => {
730730
expect(wrapper.render()).toMatchSnapshot();
731731
});
732732

733-
describe('hover placeholder', () => {
734-
const placeholder = 'custom placeholder';
735-
it('placeholder should be origin value when input value is not empty', () => {
736-
const wrapper = mount(
737-
<MomentPicker placeholder={placeholder} open defaultValue={getMoment('2020-07-22')} />,
738-
);
733+
describe('hover value', () => {
734+
it('should restore when leave', () => {
735+
const wrapper = mount(<MomentPicker open defaultValue={getMoment('2020-07-22')} />);
739736
const cell = wrapper.findCell(24);
740737
cell.simulate('mouseEnter');
741-
expect(wrapper.find('input').prop('placeholder')).toBe(placeholder);
738+
expect(wrapper.find('input').prop('value')).toBe('2020-07-24');
739+
expect(wrapper.find('.rc-picker-input').hasClass('rc-picker-input-placeholder')).toBeTruthy();
740+
741+
cell.simulate('mouseLeave');
742+
expect(wrapper.find('input').prop('value')).toBe('2020-07-22');
743+
expect(wrapper.find('.rc-picker-input').hasClass('rc-picker-input-placeholder')).toBeFalsy();
742744
});
743745

744-
it('placeholder should be target date when input value is empty', () => {
745-
const wrapper = mount(
746-
<MomentPicker placeholder={placeholder} defaultValue={getMoment('2020-07-22')} />,
747-
);
746+
it('should restore after selecting cell', () => {
747+
const wrapper = mount(<MomentPicker defaultValue={getMoment('2020-07-22')} />);
748+
wrapper.openPicker();
749+
const cell = wrapper.findCell(24);
750+
cell.simulate('mouseEnter');
751+
expect(wrapper.find('input').prop('value')).toBe('2020-07-24');
752+
expect(wrapper.find('.rc-picker-input').hasClass('rc-picker-input-placeholder')).toBeTruthy();
753+
754+
wrapper.selectCell(24);
755+
expect(wrapper.find('input').prop('value')).toBe('2020-07-24');
756+
expect(wrapper.find('.rc-picker-input').hasClass('rc-picker-input-placeholder')).toBeFalsy();
757+
});
758+
759+
it('change value when hovering', () => {
760+
const wrapper = mount(<MomentPicker defaultValue={getMoment('2020-07-22')} />);
748761
wrapper.openPicker();
762+
const cell = wrapper.findCell(24);
763+
cell.simulate('mouseEnter');
764+
expect(wrapper.find('input').prop('value')).toBe('2020-07-24');
765+
expect(wrapper.find('.rc-picker-input').hasClass('rc-picker-input-placeholder')).toBeTruthy();
766+
749767
wrapper.find('input').simulate('change', {
750768
target: {
751-
value: '',
769+
value: '2020-07-23',
752770
},
753771
});
754-
const cell = wrapper.findCell(24);
755-
cell.simulate('mouseEnter');
756-
expect(wrapper.find('input').prop('placeholder')).toBe('2020-07-24');
757-
cell.simulate('mouseLeave');
758-
expect(wrapper.find('input').prop('placeholder')).toBe(placeholder);
772+
773+
expect(wrapper.find('input').prop('value')).toBe('2020-07-23');
774+
expect(wrapper.find('.rc-picker-input').hasClass('rc-picker-input-placeholder')).toBeFalsy();
775+
759776
wrapper.closePicker();
777+
expect(wrapper.find('input').prop('value')).toBe('2020-07-23');
778+
expect(wrapper.find('.rc-picker-input').hasClass('rc-picker-input-placeholder')).toBeFalsy();
760779
});
761780
});
762781
});

0 commit comments

Comments
 (0)