Skip to content

Commit

Permalink
feat(Input): textarea support hasClear, close #4334
Browse files Browse the repository at this point in the history
  • Loading branch information
WB01081293 committed Jan 24, 2024
1 parent 4ad6511 commit 6d4800e
Show file tree
Hide file tree
Showing 8 changed files with 380 additions and 194 deletions.
18 changes: 18 additions & 0 deletions components/input/__docs__/demo/clear/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,24 @@ ReactDOM.render(
/>
<br />
<br />
<Input.TextArea
hasClear
defaultValue="clear by click"
aria-label="input with config of hasClear"
onChange={onChange}
/>
<br />
<br />
<Input.TextArea
hasClear
defaultValue="clear by click"
aria-label="input with config of hasClear"
onChange={onChange}
maxLength={100}
showLimitHint
/>
<br />
<br />
</div>,
mountNode
);
139 changes: 70 additions & 69 deletions components/input/__docs__/index.en-us.md

Large diffs are not rendered by default.

155 changes: 78 additions & 77 deletions components/input/__docs__/index.md

Large diffs are not rendered by default.

94 changes: 76 additions & 18 deletions components/input/__tests__/textarea-spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import React, { useState } from 'react';
import ReactTestUtils from 'react-dom/test-utils';
import ReactDOM from 'react-dom';
import Enzyme, { mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Expand All @@ -7,7 +8,10 @@ import assert from 'power-assert';
import Input from '../index';

Enzyme.configure({ adapter: new Adapter() });

function delay(duration) {
return new Promise(resolve => setTimeout(resolve, duration));
}
/* eslint-disable no-undef, react/jsx-filename-extension */
describe('TextArea', () => {
describe('render', () => {
let parent;
Expand All @@ -23,23 +27,55 @@ describe('TextArea', () => {
});

it('should textarea isPreview', () => {
ReactDOM.render(<Input.TextArea id="ispreview-input" isPreview defaultValue="abc" />, parent);
ReactDOM.render(
<Input.TextArea id="ispreview-input" isPreview defaultValue="abc" />,
parent
);
assert(document.querySelectorAll('#ispreview-input')[0].innerText === 'abc');
});

it('should textarea isPreview compatible value null', () => {
ReactDOM.render(<Input.TextArea id="ispreview-input-null" isPreview value={null} />, parent);
ReactDOM.render(
<Input.TextArea id="ispreview-input-null" isPreview value={null} />,
parent
);
assert(document.querySelectorAll('#ispreview-input-null')[0].innerText === '');
});

it('should textarea renderPreview', () => {
ReactDOM.render(
<Input.TextArea id="renderpreview-input" isPreview defaultValue="abc" renderPreview={() => 'ddd'} />,
<Input.TextArea
id="renderpreview-input"
isPreview
defaultValue="abc"
renderPreview={() => 'ddd'}
/>,
parent
);

assert(document.querySelectorAll('#renderpreview-input')[0].innerText === 'ddd');
});
it('should support hasClear ,close #4334', async () => {
const ref = { current: null };
function Demo() {
const [value, setValue] = useState('aaa');
ref.current = { value };
return (
<Input.TextArea
value={value}
placeholder="TextArea"
aria-label="TextArea"
hasClear
onChange={v => setValue(v)}
/>
);
}
mount(<Demo />, { attachTo: parent });
await delay(100);
const btn = parent.querySelector('.next-input-clear');
ReactTestUtils.Simulate.click(btn);
assert(ref.current.value === '');
});
});

describe('behavior', () => {
Expand All @@ -48,7 +84,9 @@ describe('TextArea', () => {
const onChange = sinon.spy();
const onFocus = sinon.spy();
const onBlur = sinon.spy();
const wrapper = mount(<Input.TextArea onChange={onChange} onFocus={onFocus} onBlur={onBlur} />);
const wrapper = mount(
<Input.TextArea onChange={onChange} onFocus={onFocus} onBlur={onBlur} />
);
wrapper.find('textarea').simulate('change', { target: { value: '20' } });
assert(onChange.calledOnce);
wrapper.find('textarea').simulate('focus');
Expand Down Expand Up @@ -125,7 +163,9 @@ describe('TextArea', () => {
});

it('should support maxLength & hasLimitHint', done => {
const wrapper = mount(<Input.TextArea defaultValue={'abcd'} maxLength={10} hasLimitHint />);
const wrapper = mount(
<Input.TextArea defaultValue={'abcd'} maxLength={10} hasLimitHint />
);
assert(!wrapper.find('.next-input-len').hasClass('next-error'));

wrapper.find('textarea').simulate('change', { target: { value: '12345678901' } });
Expand Down Expand Up @@ -176,7 +216,9 @@ describe('TextArea', () => {
<Input.TextArea
ref="textarea"
onFocus={e => {
assert(this.refs.textarea.getInstance().getInputNode() !== undefined);
assert(
this.refs.textarea.getInstance().getInputNode() !== undefined
);
}}
/>
);
Expand All @@ -191,7 +233,13 @@ describe('TextArea', () => {

it('should support getValueLength', done => {
const getValueLength = sinon.spy();
mount(<Input.TextArea defaultValue="abcdef" maxLength={10} getValueLength={getValueLength} />);
mount(
<Input.TextArea
defaultValue="abcdef"
maxLength={10}
getValueLength={getValueLength}
/>
);
assert(getValueLength.calledOnce);

let getValueLength2 = value => {
Expand All @@ -208,7 +256,12 @@ describe('TextArea', () => {
assert(wrapper.find('.next-input-len').text() === '1/10');

const wrapper2 = mount(
<Input.TextArea defaultValue="abcdef" maxLength={10} hasLimitHint getValueLength={getValueLength2} />
<Input.TextArea
defaultValue="abcdef"
maxLength={10}
hasLimitHint
getValueLength={getValueLength2}
/>
);
assert(wrapper2.find('.next-input-len').text() === '1/10');

Expand All @@ -219,15 +272,23 @@ describe('TextArea', () => {
const wrapper = mount(<Input.TextArea defaultValue="abcdef" autoHeight />);
// console.log(wrapper.find('textarea[data-real]').instance().clientHeight)
// let originHeight = wrapper.find('textarea[data-real]').instance().clientHeight;
wrapper.find('textarea[data-real]').simulate('change', { target: { value: '1\n2\n3\n4\n5\n' } });
wrapper
.find('textarea[data-real]')
.simulate('change', { target: { value: '1\n2\n3\n4\n5\n' } });

// assert(wrapper.find('textarea[data-real]').at(0).getElement().clientHeight > originHeight);

const wrapper2 = mount(<Input.TextArea defaultValue="abcdef" autoHeight={{ minRows: 2, maxRows: 4 }} />);
const wrapper2 = mount(
<Input.TextArea defaultValue="abcdef" autoHeight={{ minRows: 2, maxRows: 4 }} />
);
// console.log(wrapper2.find('textarea[data-real]').instance().clientHeight)
// let originHeight = wrapper2.find('textarea[data-real]').instance().clientHeight;
wrapper2.find('textarea[data-real]').simulate('change', { target: { value: '1\n2\n3\n4\n5\n' } });
wrapper2.find('textarea[data-real]').simulate('change', { target: { value: '1\n2\n3\n4' } });
wrapper2
.find('textarea[data-real]')
.simulate('change', { target: { value: '1\n2\n3\n4\n5\n' } });
wrapper2
.find('textarea[data-real]')
.simulate('change', { target: { value: '1\n2\n3\n4' } });

//

Expand All @@ -241,10 +302,7 @@ describe('TextArea', () => {
}
}
const wrapper = mount(<App />);
wrapper
.ref('textarea')
.getInstance()
.focus();
wrapper.ref('textarea').getInstance().focus();
wrapper.update();
// assert(wrapper.find('.next-input').hasClass('next-focus'));

Expand Down
12 changes: 2 additions & 10 deletions components/input/base.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { polyfill } from 'react-lifecycles-compat';

import ConfigProvider from '../config-provider';
import { func } from '../util';
import zhCN from '../locale/zh-cn';


class Base extends React.Component {
static propTypes = {
...ConfigProvider.propTypes,
Expand Down Expand Up @@ -252,18 +252,10 @@ class Base extends React.Component {

const content = rtl ? `${maxLength}/${len}` : `${len}/${maxLength}`;

return maxLength && showLimitHint ? <span className={classesLenWrap}>{content}</span> : null;
return maxLength && showLimitHint ? <span className={classesLenWrap}>{content}</span> : null
}

renderControl() {
const lenWrap = this.renderLength();

return lenWrap ? (
<span onClick={() => this.focus()} className={`${this.props.prefix}input-control`}>
{lenWrap}
</span>
) : null;
}

getClass() {
const { disabled, state, prefix } = this.props;
Expand Down
4 changes: 4 additions & 0 deletions components/input/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ export interface TextAreaProps extends HTMLAttributesWeak, CommonProps {
* 开启后会过滤输入法中间字母状态,文字输入完成后才会触发 onChange
*/
composition?: boolean;
/**
* 是否出现clear按钮
*/
hasClear?: boolean;
}

export class TextArea extends React.Component<TextAreaProps, any> {}
Expand Down
Loading

0 comments on commit 6d4800e

Please sign in to comment.