Skip to content

Commit

Permalink
fix: Adjust customize input detect logic
Browse files Browse the repository at this point in the history
  • Loading branch information
zombieJ committed Sep 5, 2019
1 parent 1d35b68 commit 96a7681
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 16 deletions.
15 changes: 14 additions & 1 deletion src/Selector/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface InputProps {
tabIndex: number;

onKeyDown: React.KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
onMouseDown: React.MouseEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
onChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement | HTMLElement>;
}

Expand All @@ -38,6 +39,7 @@ const Input: React.RefForwardingComponent<InputRef, InputProps> = (
accessibilityIndex,
value,
onKeyDown,
onMouseDown,
onChange,
open,
},
Expand All @@ -47,7 +49,12 @@ const Input: React.RefForwardingComponent<InputRef, InputProps> = (

const {
ref: originRef,
props: { onKeyDown: onOriginKeyDown, onChange: onOriginChange, style },
props: {
onKeyDown: onOriginKeyDown,
onChange: onOriginChange,
onMouseDown: onOriginMouseDown,
style,
},
} = inputNode;

function inputRef(node: InputRef) {
Expand Down Expand Up @@ -78,6 +85,12 @@ const Input: React.RefForwardingComponent<InputRef, InputProps> = (
onOriginKeyDown(event);
}
},
onMouseDown: (event: React.MouseEvent<HTMLElement>) => {
onMouseDown(event);
if (onOriginMouseDown) {
onOriginMouseDown(event);
}
},
onChange: (event: React.ChangeEvent<HTMLElement>) => {
onChange(event);
if (onOriginChange) {
Expand Down
2 changes: 2 additions & 0 deletions src/Selector/MultipleSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const SelectSelector: React.FC<SelectorProps> = ({
onSelect,
onInputChange,
onInputKeyDown,
onInputMouseDown,
}) => {
const [motionAppear, setMotionAppear] = React.useState(false);
const measureRef = React.useRef<HTMLSpanElement>(null);
Expand Down Expand Up @@ -170,6 +171,7 @@ const SelectSelector: React.FC<SelectorProps> = ({
accessibilityIndex={accessibilityIndex}
value={searchValue}
onKeyDown={onInputKeyDown}
onMouseDown={onInputMouseDown}
onChange={onInputChange}
tabIndex={tabIndex}
/>
Expand Down
2 changes: 2 additions & 0 deletions src/Selector/SingleSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const SingleSelector: React.FC<SelectorProps> = ({
activeValue,

onInputKeyDown,
onInputMouseDown,
onInputChange,
}) => {
const combobox = mode === 'combobox';
Expand Down Expand Up @@ -55,6 +56,7 @@ const SingleSelector: React.FC<SelectorProps> = ({
accessibilityIndex={accessibilityIndex}
value={inputValue}
onKeyDown={onInputKeyDown}
onMouseDown={onInputMouseDown}
onChange={onInputChange}
tabIndex={tabIndex}
/>
Expand Down
15 changes: 14 additions & 1 deletion src/Selector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import MultipleSelector from './MultipleSelector';
import SingleSelector from './SingleSelector';
import { LabelValueType, RawValueType } from '../interface/generator';
import { RenderNode, Mode } from '../interface';
import useLock from '../hooks/useLock';

export interface InnerSelectorProps {
prefixCls: string;
Expand All @@ -32,6 +33,7 @@ export interface InnerSelectorProps {
tabIndex?: number;

onInputKeyDown: React.KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement>;
onInputMouseDown: React.MouseEventHandler<HTMLInputElement | HTMLTextAreaElement>;
onInputChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>;
}

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

// ====================== Input ======================
const [getInputMouseDown, setInputMouseDown] = useLock(0);

const onInternalInputKeyDown: React.KeyboardEventHandler<HTMLInputElement> = event => {
const { which } = event;

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

/**
* We can not use `findDOMNode` sine it will get warning,
* have to use timer to check if is input element.
*/
const onInternalInputMouseDown: React.MouseEventHandler<HTMLInputElement> = event => {
setInputMouseDown(true);
};

const onInputChange = ({ target: { value } }) => {
if (onSearch(value) !== false) {
onToggleOpen(true);
Expand All @@ -129,7 +141,7 @@ const Selector: React.RefForwardingComponent<RefSelectorProps, SelectorProps> =
};

const onMouseDown: React.MouseEventHandler<HTMLElement> = event => {
if (event.target !== inputRef.current) {
if (event.target !== inputRef.current && !getInputMouseDown()) {
event.preventDefault();
}

Expand All @@ -140,6 +152,7 @@ const Selector: React.RefForwardingComponent<RefSelectorProps, SelectorProps> =
const sharedProps = {
inputRef,
onInputKeyDown: onInternalInputKeyDown,
onInputMouseDown: onInternalInputMouseDown,
onInputChange,
};

Expand Down
5 changes: 3 additions & 2 deletions src/generate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
import { OptionListProps, RefOptionListProps } from './OptionList';
import { toInnerValue, toOuterValues, removeLastEnabledValue, getUUID } from './utils/commonUtil';
import TransBtn from './TransBtn';
import { useLock } from './hooks/useLock';
import useLock from './hooks/useLock';
import useDelayReset from './hooks/useDelayReset';
import useLayoutEffect from './hooks/useLayoutEffect';
import { getSeparatedContent } from './utils/valueUtil';
Expand Down Expand Up @@ -574,7 +574,8 @@ export default function generateSelector<
* - true: Search text is empty when first time backspace down
* - false: Search text is not empty when first time backspace down
*/
const [clearLock, setClearLock] = useLock();
const [getClearLock, setClearLock] = useLock();
const clearLock = getClearLock();

// KeyDown
const onInternalKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (event, ...rest) => {
Expand Down
20 changes: 10 additions & 10 deletions src/hooks/useLock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@ import * as React from 'react';
* If set to `false` and then set to `true`, will change to `true`.
* And after time duration, it will back to `null` automatically.
*/
export function useLock(duration: number = 250): [boolean, (lock: boolean) => void] {
const [lock, setLock] = React.useState<boolean>(null);
const lockRef = React.useRef<number>(null);
export default function useLock(duration: number = 250): [() => boolean, (lock: boolean) => void] {
const lockRef = React.useRef<boolean>(null);
const timeoutRef = React.useRef<number>(null);

// Clean up
React.useEffect(
() => () => {
window.clearTimeout(lockRef.current);
window.clearTimeout(timeoutRef.current);
},
[],
);

function doLock(locked: boolean) {
if (locked || lock === null) {
setLock(locked);
if (locked || lockRef.current === null) {
lockRef.current = locked;
}

window.clearTimeout(lockRef.current);
lockRef.current = window.setTimeout(() => {
setLock(null);
window.clearTimeout(timeoutRef.current);
timeoutRef.current = window.setTimeout(() => {
lockRef.current = null;
}, duration);
}

return [lock, doLock];
return [() => lockRef.current, doLock];
}
2 changes: 1 addition & 1 deletion tests/Hooks.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { mount } from 'enzyme';
import { useLock } from '../src/hooks/useLock';
import useLock from '../src/hooks/useLock';
import { injectRunAllTimers } from './utils/common';

describe('Hooks', () => {
Expand Down
12 changes: 11 additions & 1 deletion tests/Select.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -722,12 +722,19 @@ describe('Select.Basic', () => {
it('combobox could customize input element', () => {
const onKeyDown = jest.fn();
const onChange = jest.fn();
const onMouseDown = jest.fn();
const textareaRef = jest.fn();
const mouseDownPreventDefault = jest.fn();
const wrapper = mount(
<Select
mode="combobox"
getInputElement={() => (
<textarea onKeyDown={onKeyDown} onChange={onChange} ref={textareaRef} />
<textarea
onKeyDown={onKeyDown}
onChange={onChange}
onMouseDown={onMouseDown}
ref={textareaRef}
/>
)}
>
<Option value="1">1</Option>
Expand All @@ -740,13 +747,16 @@ describe('Select.Basic', () => {
wrapper
.find('.rc-select')
.find('textarea')
.simulate('mouseDown', { preventDefault: mouseDownPreventDefault })
.simulate('keyDown', { which: KeyCode.NUM_ONE })
.simulate('change', { value: '1' });

selectItem(wrapper);
expect(wrapper.find('textarea').props().value).toEqual('1');
expect(mouseDownPreventDefault).not.toHaveBeenCalled();
expect(onKeyDown).toHaveBeenCalled();
expect(onChange).toHaveBeenCalled();
expect(onMouseDown).toHaveBeenCalled();
expect(textareaRef).toHaveBeenCalled();
});

Expand Down

0 comments on commit 96a7681

Please sign in to comment.