mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-19 06:43:16 +08:00
fix: Input affix prevent dropdown focus (#22887)
* adjust focus logic * update logic
This commit is contained in:
parent
b369717181
commit
89abacac31
@ -42,6 +42,16 @@ interface ClearableInputProps extends BasicProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ClearableLabeledInput extends React.Component<ClearableInputProps> {
|
class ClearableLabeledInput extends React.Component<ClearableInputProps> {
|
||||||
|
/** @private Do not use out of this class. We do not promise this is always keep. */
|
||||||
|
private containerRef = React.createRef<HTMLSpanElement>();
|
||||||
|
|
||||||
|
onInputMouseUp: React.MouseEventHandler = e => {
|
||||||
|
if (this.containerRef.current?.contains(e.target as Element)) {
|
||||||
|
const { triggerFocus } = this.props;
|
||||||
|
triggerFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
renderClearIcon(prefixCls: string) {
|
renderClearIcon(prefixCls: string) {
|
||||||
const { allowClear, value, disabled, readOnly, inputType, handleReset } = this.props;
|
const { allowClear, value, disabled, readOnly, inputType, handleReset } = this.props;
|
||||||
if (
|
if (
|
||||||
@ -86,7 +96,6 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
|
|||||||
allowClear,
|
allowClear,
|
||||||
direction,
|
direction,
|
||||||
style,
|
style,
|
||||||
triggerFocus,
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const suffixNode = this.renderSuffix(prefixCls);
|
const suffixNode = this.renderSuffix(prefixCls);
|
||||||
if (!hasPrefixSuffix(this.props)) {
|
if (!hasPrefixSuffix(this.props)) {
|
||||||
@ -106,7 +115,12 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
|
|||||||
[`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl',
|
[`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl',
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<span className={affixWrapperCls} style={style} onMouseUp={triggerFocus}>
|
<span
|
||||||
|
ref={this.containerRef}
|
||||||
|
className={affixWrapperCls}
|
||||||
|
style={style}
|
||||||
|
onMouseUp={this.onInputMouseUp}
|
||||||
|
>
|
||||||
{prefixNode}
|
{prefixNode}
|
||||||
{React.cloneElement(element, {
|
{React.cloneElement(element, {
|
||||||
style: null,
|
style: null,
|
||||||
|
@ -174,10 +174,7 @@ describe('TextArea allowClear', () => {
|
|||||||
wrapper.find('textarea').simulate('change', { target: { value: '111' } });
|
wrapper.find('textarea').simulate('change', { target: { value: '111' } });
|
||||||
expect(wrapper.find('textarea').getDOMNode().value).toEqual('111');
|
expect(wrapper.find('textarea').getDOMNode().value).toEqual('111');
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(wrapper.render()).toMatchSnapshot();
|
||||||
wrapper
|
wrapper.find('.ant-input-textarea-clear-icon').at(0).simulate('click');
|
||||||
.find('.ant-input-textarea-clear-icon')
|
|
||||||
.at(0)
|
|
||||||
.simulate('click');
|
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(wrapper.render()).toMatchSnapshot();
|
||||||
expect(wrapper.find('textarea').getDOMNode().value).toEqual('');
|
expect(wrapper.find('textarea').getDOMNode().value).toEqual('');
|
||||||
});
|
});
|
||||||
@ -210,18 +207,10 @@ describe('TextArea allowClear', () => {
|
|||||||
argumentEventObjectValue = e.target.value;
|
argumentEventObjectValue = e.target.value;
|
||||||
};
|
};
|
||||||
const wrapper = mount(<TextArea allowClear defaultValue="111" onChange={onChange} />);
|
const wrapper = mount(<TextArea allowClear defaultValue="111" onChange={onChange} />);
|
||||||
wrapper
|
wrapper.find('.ant-input-textarea-clear-icon').at(0).simulate('click');
|
||||||
.find('.ant-input-textarea-clear-icon')
|
|
||||||
.at(0)
|
|
||||||
.simulate('click');
|
|
||||||
expect(argumentEventObject.type).toBe('click');
|
expect(argumentEventObject.type).toBe('click');
|
||||||
expect(argumentEventObjectValue).toBe('');
|
expect(argumentEventObjectValue).toBe('');
|
||||||
expect(
|
expect(wrapper.find('textarea').at(0).getDOMNode().value).toBe('');
|
||||||
wrapper
|
|
||||||
.find('textarea')
|
|
||||||
.at(0)
|
|
||||||
.getDOMNode().value,
|
|
||||||
).toBe('');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should trigger event correctly on controlled mode', () => {
|
it('should trigger event correctly on controlled mode', () => {
|
||||||
@ -232,32 +221,16 @@ describe('TextArea allowClear', () => {
|
|||||||
argumentEventObjectValue = e.target.value;
|
argumentEventObjectValue = e.target.value;
|
||||||
};
|
};
|
||||||
const wrapper = mount(<TextArea allowClear value="111" onChange={onChange} />);
|
const wrapper = mount(<TextArea allowClear value="111" onChange={onChange} />);
|
||||||
wrapper
|
wrapper.find('.ant-input-textarea-clear-icon').at(0).simulate('click');
|
||||||
.find('.ant-input-textarea-clear-icon')
|
|
||||||
.at(0)
|
|
||||||
.simulate('click');
|
|
||||||
expect(argumentEventObject.type).toBe('click');
|
expect(argumentEventObject.type).toBe('click');
|
||||||
expect(argumentEventObjectValue).toBe('');
|
expect(argumentEventObjectValue).toBe('');
|
||||||
expect(
|
expect(wrapper.find('textarea').at(0).getDOMNode().value).toBe('111');
|
||||||
wrapper
|
|
||||||
.find('textarea')
|
|
||||||
.at(0)
|
|
||||||
.getDOMNode().value,
|
|
||||||
).toBe('111');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should focus textarea after clear', () => {
|
it('should focus textarea after clear', () => {
|
||||||
const wrapper = mount(<TextArea allowClear defaultValue="111" />, { attachTo: document.body });
|
const wrapper = mount(<TextArea allowClear defaultValue="111" />, { attachTo: document.body });
|
||||||
wrapper
|
wrapper.find('.ant-input-textarea-clear-icon').at(0).simulate('click');
|
||||||
.find('.ant-input-textarea-clear-icon')
|
expect(document.activeElement).toBe(wrapper.find('textarea').at(0).getDOMNode());
|
||||||
.at(0)
|
|
||||||
.simulate('click');
|
|
||||||
expect(document.activeElement).toBe(
|
|
||||||
wrapper
|
|
||||||
.find('textarea')
|
|
||||||
.at(0)
|
|
||||||
.getDOMNode(),
|
|
||||||
);
|
|
||||||
wrapper.unmount();
|
wrapper.unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -277,20 +250,31 @@ describe('TextArea allowClear', () => {
|
|||||||
expect(wrapper.find('input').props().value).toEqual('Light');
|
expect(wrapper.find('input').props().value).toEqual('Light');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('click outside should also get focus', () => {
|
describe('click focus', () => {
|
||||||
const wrapper = mount(<Input suffix={<span className="test-suffix" />} />);
|
it('click outside should also get focus', () => {
|
||||||
const onFocus = jest.spyOn(wrapper.find('input').instance(), 'focus');
|
const wrapper = mount(<Input suffix={<span className="test-suffix" />} />);
|
||||||
wrapper.find('.test-suffix').simulate('mouseUp');
|
const onFocus = jest.spyOn(wrapper.find('input').instance(), 'focus');
|
||||||
expect(onFocus).toHaveBeenCalled();
|
wrapper.find('.test-suffix').simulate('mouseUp');
|
||||||
|
expect(onFocus).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('not get focus if out of component', () => {
|
||||||
|
const wrapper = mount(<Input suffix={<span className="test-suffix" />} />);
|
||||||
|
const onFocus = jest.spyOn(wrapper.find('input').instance(), 'focus');
|
||||||
|
const ele = document.createElement('span');
|
||||||
|
document.body.appendChild(ele);
|
||||||
|
wrapper.find('.test-suffix').simulate('mouseUp', {
|
||||||
|
target: ele,
|
||||||
|
});
|
||||||
|
expect(onFocus).not.toHaveBeenCalled();
|
||||||
|
document.body.removeChild(ele);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('scroll to bottom when autoSize', async () => {
|
it('scroll to bottom when autoSize', async () => {
|
||||||
const wrapper = mount(<Input.TextArea autoSize />, { attachTo: document.body });
|
const wrapper = mount(<Input.TextArea autoSize />, { attachTo: document.body });
|
||||||
wrapper.find('textarea').simulate('focus');
|
wrapper.find('textarea').simulate('focus');
|
||||||
wrapper
|
wrapper.find('textarea').getDOMNode().focus();
|
||||||
.find('textarea')
|
|
||||||
.getDOMNode()
|
|
||||||
.focus();
|
|
||||||
const setSelectionRangeFn = jest.spyOn(
|
const setSelectionRangeFn = jest.spyOn(
|
||||||
wrapper.find('textarea').getDOMNode(),
|
wrapper.find('textarea').getDOMNode(),
|
||||||
'setSelectionRange',
|
'setSelectionRange',
|
||||||
|
Loading…
Reference in New Issue
Block a user