2018-03-01 17:53:29 +00:00
|
|
|
import React, { HTMLProps } from 'react';
|
2018-05-13 19:24:50 +00:00
|
|
|
import classnames from 'classnames';
|
2018-03-01 17:53:29 +00:00
|
|
|
import './Input.scss';
|
|
|
|
|
|
|
|
interface State {
|
|
|
|
hasBlurred: boolean;
|
2018-05-13 19:24:50 +00:00
|
|
|
/**
|
|
|
|
* @description when the input has not had any values inputted yet
|
|
|
|
* e.g. "Pristine" condition
|
|
|
|
*/
|
|
|
|
isStateless: boolean;
|
2018-03-01 17:53:29 +00:00
|
|
|
}
|
|
|
|
|
2018-05-13 19:24:50 +00:00
|
|
|
interface OwnProps extends HTMLProps<HTMLInputElement> {
|
|
|
|
isValid: boolean;
|
|
|
|
showValidAsPlain?: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
class Input extends React.Component<OwnProps, State> {
|
2018-03-01 17:53:29 +00:00
|
|
|
public state: State = {
|
2018-05-13 19:24:50 +00:00
|
|
|
hasBlurred: false,
|
|
|
|
isStateless: true
|
2018-03-01 17:53:29 +00:00
|
|
|
};
|
2018-03-03 19:11:05 +00:00
|
|
|
|
2018-03-01 17:53:29 +00:00
|
|
|
public render() {
|
2018-05-13 19:24:50 +00:00
|
|
|
const { showValidAsPlain, isValid, ...htmlProps } = this.props;
|
|
|
|
const hasValue = !!this.props.value && this.props.value.toString().length > 0;
|
|
|
|
const classname = classnames(
|
|
|
|
this.props.className,
|
|
|
|
'input-group-input',
|
|
|
|
'form-control',
|
|
|
|
this.state.isStateless
|
|
|
|
? ''
|
|
|
|
: isValid ? (showValidAsPlain ? '' : `is-valid valid`) : `is-invalid invalid`,
|
|
|
|
this.state.hasBlurred && 'has-blurred',
|
|
|
|
hasValue && 'has-value'
|
|
|
|
);
|
|
|
|
|
2018-03-01 17:53:29 +00:00
|
|
|
return (
|
|
|
|
<input
|
2018-05-13 19:24:50 +00:00
|
|
|
{...htmlProps}
|
2018-03-01 17:53:29 +00:00
|
|
|
onBlur={e => {
|
|
|
|
this.setState({ hasBlurred: true });
|
|
|
|
if (this.props && this.props.onBlur) {
|
|
|
|
this.props.onBlur(e);
|
|
|
|
}
|
|
|
|
}}
|
2018-05-13 19:24:50 +00:00
|
|
|
onChange={this.handleOnChange}
|
2018-03-03 19:11:05 +00:00
|
|
|
onWheel={this.props.type === 'number' ? this.preventNumberScroll : undefined}
|
2018-05-13 19:24:50 +00:00
|
|
|
className={classname}
|
2018-03-01 17:53:29 +00:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
2018-03-03 19:11:05 +00:00
|
|
|
|
2018-05-13 19:24:50 +00:00
|
|
|
private handleOnChange = (args: React.FormEvent<HTMLInputElement>) => {
|
|
|
|
if (this.state.isStateless) {
|
|
|
|
this.setState({ isStateless: false });
|
|
|
|
}
|
|
|
|
if (this.props.onChange) {
|
|
|
|
this.props.onChange(args);
|
|
|
|
}
|
|
|
|
};
|
2018-03-03 19:11:05 +00:00
|
|
|
// When number inputs are scrolled on while in focus, the number changes. So we blur
|
|
|
|
// it if it's focused to prevent that behavior, without preventing the scroll.
|
|
|
|
private preventNumberScroll(ev: React.WheelEvent<HTMLInputElement>) {
|
|
|
|
if (document.activeElement === ev.currentTarget) {
|
|
|
|
ev.currentTarget.blur();
|
|
|
|
}
|
|
|
|
}
|
2018-03-01 17:53:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export default Input;
|