Skip to content

Commit

Permalink
feat(Input): add inputComponent prop (#1413)
Browse files Browse the repository at this point in the history
  • Loading branch information
mgcrea authored and iRoachie committed Sep 13, 2018
1 parent 4fd270b commit 60e5201
Show file tree
Hide file tree
Showing 5 changed files with 1,088 additions and 18 deletions.
39 changes: 25 additions & 14 deletions docs/input.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,21 @@ import { Input } from 'react-native-elements';

> This component inherits [all native TextInput props that come with a standard React Native TextInput element](https://facebook.github.io/react-native/docs/textinput.html), along with the following:
* [`containerStyle`](#containerstyle)
* [`inputContainerStyle`](#inputcontainerstyle)
* [`errorMessage`](#errormessage)
* [`errorStyle`](#errorstyle)
* [`errorProps`](#errorprops)
* [`inputStyle`](#inputstyle)
* [`label`](#label)
* [`labelStyle`](#labelStyle)
* [`labelProps`](#labelprops)
* [`leftIcon`](#lefticon)
* [`leftIconContainerStyle`](#lefticoncontainerstyle)
* [`rightIcon`](#righticon)
* [`rightIconContainerStyle`](#righticoncontainerstyle)
* [`shake`](#shake)
- [`containerStyle`](#containerstyle)
- [`inputContainerStyle`](#inputcontainerstyle)
- [`errorMessage`](#errormessage)
- [`errorStyle`](#errorstyle)
- [`errorProps`](#errorprops)
- [`inputComponent`](#inputComponent)
- [`inputStyle`](#inputstyle)
- [`label`](#label)
- [`labelStyle`](#labelStyle)
- [`labelProps`](#labelprops)
- [`leftIcon`](#lefticon)
- [`leftIconContainerStyle`](#lefticoncontainerstyle)
- [`rightIcon`](#righticon)
- [`rightIconContainerStyle`](#righticoncontainerstyle)
- [`shake`](#shake)

---

Expand Down Expand Up @@ -116,6 +117,16 @@ props to be passed to the React Native `Text` component used to display the erro

---

### `inputComponent`

component that will be rendered in place of the React Native `TextInput` (optional)

| Type | Default |
| :--------------------: | :-------: |
| React Native Component | TextInput |

---

### `inputStyle`

style that will be passed to the `style` props of the React Native `TextInput` (optional)
Expand Down
5 changes: 5 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,11 @@ export interface InputProps extends TextInputProperties {
*/
rightIconContainerStyle?: StyleProp<ViewStyle>;

/**
* Renders component in place of the React Native `TextInput` (optional)
*/
inputComponent?: React.ComponentClass<any>;

/**
* Adds styling to input component (optional)
*/
Expand Down
16 changes: 12 additions & 4 deletions src/input/Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
Text,
View,
TextInput,
Dimensions,
Animated,
Easing,
Platform,
Expand Down Expand Up @@ -65,6 +64,7 @@ class Input extends Component {
leftIconContainerStyle,
rightIcon,
rightIconContainerStyle,
inputComponent: InputComponent = TextInput,
inputStyle,
errorStyle,
errorProps,
Expand All @@ -81,7 +81,11 @@ class Input extends Component {

return (
<View style={[{ width: '90%' }, containerStyle]}>
{!!label && <Text {...labelProps} style={[styles.label, labelStyle]}>{label}</Text>}
{!!label && (
<Text {...labelProps} style={[styles.label, labelStyle]}>
{label}
</Text>
)}
<Animated.View
style={[
styles.inputContainer,
Expand All @@ -100,7 +104,7 @@ class Input extends Component {
{renderNode(Icon, leftIcon)}
</View>
)}
<TextInput
<InputComponent
underlineColorAndroid="transparent"
{...attributes}
ref={this._inputRef}
Expand All @@ -113,7 +117,10 @@ class Input extends Component {
)}
</Animated.View>
{!!errorMessage && (
<Text {...errorProps} style={[styles.error, errorStyle && errorStyle]}>
<Text
{...errorProps}
style={[styles.error, errorStyle && errorStyle]}
>
{errorMessage}
</Text>
)}
Expand All @@ -133,6 +140,7 @@ Input.propTypes = {
rightIconContainerStyle: ViewPropTypes.style,

inputStyle: Text.propTypes.style,
inputComponent: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

shake: PropTypes.any,

Expand Down
133 changes: 133 additions & 0 deletions src/input/__tests__/Input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import React from 'react';
import { shallow } from 'enzyme';
import { View } from 'react-native';
import toJson from 'enzyme-to-json';
import Input from '../Input';

describe('Input component', () => {
it('should match snapshot', () => {
const component = shallow(<Input />);

expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
describe('containerStyle prop', () => {
it('should match snapshot', () => {
const component = shallow(<Input containerStyle={{ width: 200 }} />);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
});
describe('inputContainerStyle prop', () => {
it('should match snapshot', () => {
const component = shallow(<Input inputContainerStyle={{ width: 200 }} />);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
});
describe('inputStyle prop', () => {
it('should match snapshot', () => {
const component = shallow(<Input inputStyle={{ width: 200 }} />);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
});
describe('leftIcon prop', () => {
it('should match snapshot', () => {
const component = shallow(
<Input leftIcon={{ type: 'feather', name: 'user' }} />
);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
it('along with leftIconContainerStyle should match snapshot', () => {
const component = shallow(
<Input
leftIcon={{ type: 'feather', name: 'user' }}
leftIconContainerStyle={{ width: 200 }}
/>
);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
});
describe('rightIcon prop', () => {
it('should match snapshot', () => {
const component = shallow(
<Input rightIcon={{ type: 'feather', name: 'user' }} />
);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
it('along with rightIconContainerStyle should match snapshot', () => {
const component = shallow(
<Input
rightIcon={{ type: 'feather', name: 'user' }}
rightIconContainerStyle={{ width: 200 }}
/>
);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
});
describe('label prop', () => {
it('should match snapshot', () => {
const component = shallow(<Input label="My Label" />);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
it('along with labelStyle should match snapshot', () => {
const component = shallow(
<Input label="My Label" labelStyle={{ width: 200 }} />
);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
});
describe('errorMessage prop', () => {
it('should match snapshot', () => {
const component = shallow(<Input errorMessage="My Error Message" />);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
it('along with errorStyle should match snapshot', () => {
const component = shallow(
<Input errorMessage="My Error Message" errorStyle={{ width: 200 }} />
);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
});
describe('placeholder prop', () => {
it('should match snapshot', () => {
const component = shallow(<Input placeholder="My Placeholder" />);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
});
describe('inputComponent prop', () => {
const CustomComponent = props => <View {...props}>Custom!</View>;
it('should match snapshot', () => {
const component = shallow(<Input inputComponent={CustomComponent} />);
expect(component.length).toBe(1);
expect(toJson(component)).toMatchSnapshot();
});
});
// TextInput props
describe('onTouch prop', () => {
it('should properly call callback', () => {
const onTouchSpy = jest.fn();
const component = shallow(<Input onTouch={onTouchSpy} />);
component.find('TextInput').simulate('touch');
expect(onTouchSpy).toHaveBeenCalledTimes(1);
});
});
describe('onFocus prop', () => {
it('should properly call callback', () => {
const onFocusSpy = jest.fn();
const component = shallow(<Input onFocus={onFocusSpy} />);
component.find('TextInput').simulate('focus');
expect(onFocusSpy).toHaveBeenCalledTimes(1);
});
});
});

0 comments on commit 60e5201

Please sign in to comment.