Skip to content

Commit 96a7681

Browse files
committed
fix: Adjust customize input detect logic
1 parent 1d35b68 commit 96a7681

File tree

8 files changed

+57
-16
lines changed

8 files changed

+57
-16
lines changed

src/Selector/Input.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ interface InputProps {
1515
tabIndex: number;
1616

1717
onKeyDown: React.KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
18+
onMouseDown: React.MouseEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
1819
onChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
1920
}
2021

@@ -38,6 +39,7 @@ const Input: React.RefForwardingComponent<InputRef, InputProps> = (
3839
accessibilityIndex,
3940
value,
4041
onKeyDown,
42+
onMouseDown,
4143
onChange,
4244
open,
4345
},
@@ -47,7 +49,12 @@ const Input: React.RefForwardingComponent<InputRef, InputProps> = (
4749

4850
const {
4951
ref: originRef,
50-
props: { onKeyDown: onOriginKeyDown, onChange: onOriginChange, style },
52+
props: {
53+
onKeyDown: onOriginKeyDown,
54+
onChange: onOriginChange,
55+
onMouseDown: onOriginMouseDown,
56+
style,
57+
},
5158
} = inputNode;
5259

5360
function inputRef(node: InputRef) {
@@ -78,6 +85,12 @@ const Input: React.RefForwardingComponent<InputRef, InputProps> = (
7885
onOriginKeyDown(event);
7986
}
8087
},
88+
onMouseDown: (event: React.MouseEvent<HTMLElement>) => {
89+
onMouseDown(event);
90+
if (onOriginMouseDown) {
91+
onOriginMouseDown(event);
92+
}
93+
},
8194
onChange: (event: React.ChangeEvent<HTMLElement>) => {
8295
onChange(event);
8396
if (onOriginChange) {

src/Selector/MultipleSelector.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const SelectSelector: React.FC<SelectorProps> = ({
5353
onSelect,
5454
onInputChange,
5555
onInputKeyDown,
56+
onInputMouseDown,
5657
}) => {
5758
const [motionAppear, setMotionAppear] = React.useState(false);
5859
const measureRef = React.useRef<HTMLSpanElement>(null);
@@ -170,6 +171,7 @@ const SelectSelector: React.FC<SelectorProps> = ({
170171
accessibilityIndex={accessibilityIndex}
171172
value={searchValue}
172173
onKeyDown={onInputKeyDown}
174+
onMouseDown={onInputMouseDown}
173175
onChange={onInputChange}
174176
tabIndex={tabIndex}
175177
/>

src/Selector/SingleSelector.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const SingleSelector: React.FC<SelectorProps> = ({
2727
activeValue,
2828

2929
onInputKeyDown,
30+
onInputMouseDown,
3031
onInputChange,
3132
}) => {
3233
const combobox = mode === 'combobox';
@@ -55,6 +56,7 @@ const SingleSelector: React.FC<SelectorProps> = ({
5556
accessibilityIndex={accessibilityIndex}
5657
value={inputValue}
5758
onKeyDown={onInputKeyDown}
59+
onMouseDown={onInputMouseDown}
5860
onChange={onInputChange}
5961
tabIndex={tabIndex}
6062
/>

src/Selector/index.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import MultipleSelector from './MultipleSelector';
1414
import SingleSelector from './SingleSelector';
1515
import { LabelValueType, RawValueType } from '../interface/generator';
1616
import { RenderNode, Mode } from '../interface';
17+
import useLock from '../hooks/useLock';
1718

1819
export interface InnerSelectorProps {
1920
prefixCls: string;
@@ -32,6 +33,7 @@ export interface InnerSelectorProps {
3233
tabIndex?: number;
3334

3435
onInputKeyDown: React.KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement>;
36+
onInputMouseDown: React.MouseEventHandler<HTMLInputElement | HTMLTextAreaElement>;
3537
onInputChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>;
3638
}
3739

@@ -98,6 +100,8 @@ const Selector: React.RefForwardingComponent<RefSelectorProps, SelectorProps> =
98100
}));
99101

100102
// ====================== Input ======================
103+
const [getInputMouseDown, setInputMouseDown] = useLock(0);
104+
101105
const onInternalInputKeyDown: React.KeyboardEventHandler<HTMLInputElement> = event => {
102106
const { which } = event;
103107

@@ -114,6 +118,14 @@ const Selector: React.RefForwardingComponent<RefSelectorProps, SelectorProps> =
114118
}
115119
};
116120

121+
/**
122+
* We can not use `findDOMNode` sine it will get warning,
123+
* have to use timer to check if is input element.
124+
*/
125+
const onInternalInputMouseDown: React.MouseEventHandler<HTMLInputElement> = event => {
126+
setInputMouseDown(true);
127+
};
128+
117129
const onInputChange = ({ target: { value } }) => {
118130
if (onSearch(value) !== false) {
119131
onToggleOpen(true);
@@ -129,7 +141,7 @@ const Selector: React.RefForwardingComponent<RefSelectorProps, SelectorProps> =
129141
};
130142

131143
const onMouseDown: React.MouseEventHandler<HTMLElement> = event => {
132-
if (event.target !== inputRef.current) {
144+
if (event.target !== inputRef.current && !getInputMouseDown()) {
133145
event.preventDefault();
134146
}
135147

@@ -140,6 +152,7 @@ const Selector: React.RefForwardingComponent<RefSelectorProps, SelectorProps> =
140152
const sharedProps = {
141153
inputRef,
142154
onInputKeyDown: onInternalInputKeyDown,
155+
onInputMouseDown: onInternalInputMouseDown,
143156
onInputChange,
144157
};
145158

src/generate.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
import { OptionListProps, RefOptionListProps } from './OptionList';
3030
import { toInnerValue, toOuterValues, removeLastEnabledValue, getUUID } from './utils/commonUtil';
3131
import TransBtn from './TransBtn';
32-
import { useLock } from './hooks/useLock';
32+
import useLock from './hooks/useLock';
3333
import useDelayReset from './hooks/useDelayReset';
3434
import useLayoutEffect from './hooks/useLayoutEffect';
3535
import { getSeparatedContent } from './utils/valueUtil';
@@ -574,7 +574,8 @@ export default function generateSelector<
574574
* - true: Search text is empty when first time backspace down
575575
* - false: Search text is not empty when first time backspace down
576576
*/
577-
const [clearLock, setClearLock] = useLock();
577+
const [getClearLock, setClearLock] = useLock();
578+
const clearLock = getClearLock();
578579

579580
// KeyDown
580581
const onInternalKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (event, ...rest) => {

src/hooks/useLock.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,28 @@ import * as React from 'react';
66
* If set to `false` and then set to `true`, will change to `true`.
77
* And after time duration, it will back to `null` automatically.
88
*/
9-
export function useLock(duration: number = 250): [boolean, (lock: boolean) => void] {
10-
const [lock, setLock] = React.useState<boolean>(null);
11-
const lockRef = React.useRef<number>(null);
9+
export default function useLock(duration: number = 250): [() => boolean, (lock: boolean) => void] {
10+
const lockRef = React.useRef<boolean>(null);
11+
const timeoutRef = React.useRef<number>(null);
1212

1313
// Clean up
1414
React.useEffect(
1515
() => () => {
16-
window.clearTimeout(lockRef.current);
16+
window.clearTimeout(timeoutRef.current);
1717
},
1818
[],
1919
);
2020

2121
function doLock(locked: boolean) {
22-
if (locked || lock === null) {
23-
setLock(locked);
22+
if (locked || lockRef.current === null) {
23+
lockRef.current = locked;
2424
}
2525

26-
window.clearTimeout(lockRef.current);
27-
lockRef.current = window.setTimeout(() => {
28-
setLock(null);
26+
window.clearTimeout(timeoutRef.current);
27+
timeoutRef.current = window.setTimeout(() => {
28+
lockRef.current = null;
2929
}, duration);
3030
}
3131

32-
return [lock, doLock];
32+
return [() => lockRef.current, doLock];
3333
}

tests/Hooks.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import { mount } from 'enzyme';
3-
import { useLock } from '../src/hooks/useLock';
3+
import useLock from '../src/hooks/useLock';
44
import { injectRunAllTimers } from './utils/common';
55

66
describe('Hooks', () => {

tests/Select.test.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -722,12 +722,19 @@ describe('Select.Basic', () => {
722722
it('combobox could customize input element', () => {
723723
const onKeyDown = jest.fn();
724724
const onChange = jest.fn();
725+
const onMouseDown = jest.fn();
725726
const textareaRef = jest.fn();
727+
const mouseDownPreventDefault = jest.fn();
726728
const wrapper = mount(
727729
<Select
728730
mode="combobox"
729731
getInputElement={() => (
730-
<textarea onKeyDown={onKeyDown} onChange={onChange} ref={textareaRef} />
732+
<textarea
733+
onKeyDown={onKeyDown}
734+
onChange={onChange}
735+
onMouseDown={onMouseDown}
736+
ref={textareaRef}
737+
/>
731738
)}
732739
>
733740
<Option value="1">1</Option>
@@ -740,13 +747,16 @@ describe('Select.Basic', () => {
740747
wrapper
741748
.find('.rc-select')
742749
.find('textarea')
750+
.simulate('mouseDown', { preventDefault: mouseDownPreventDefault })
743751
.simulate('keyDown', { which: KeyCode.NUM_ONE })
744752
.simulate('change', { value: '1' });
745753

746754
selectItem(wrapper);
747755
expect(wrapper.find('textarea').props().value).toEqual('1');
756+
expect(mouseDownPreventDefault).not.toHaveBeenCalled();
748757
expect(onKeyDown).toHaveBeenCalled();
749758
expect(onChange).toHaveBeenCalled();
759+
expect(onMouseDown).toHaveBeenCalled();
750760
expect(textareaRef).toHaveBeenCalled();
751761
});
752762

0 commit comments

Comments
 (0)