1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00
metamask-extension/ui/components/ui/unit-input/unit-input.component.js

126 lines
3.2 KiB
JavaScript

import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
function removeLeadingZeroes(str) {
return str.replace(/^0*(?=\d)/u, '');
}
/**
* Component that attaches a suffix or unit of measurement trailing user input, ex. 'ETH'. Also
* allows rendering a child component underneath the input to, for example, display conversions of
* the shown suffix.
*/
export default class UnitInput extends PureComponent {
static propTypes = {
dataTestId: PropTypes.string,
children: PropTypes.node,
actionComponent: PropTypes.node,
error: PropTypes.bool,
onChange: PropTypes.func,
onBlur: PropTypes.func,
placeholder: PropTypes.string,
suffix: PropTypes.string,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};
static defaultProps = {
value: '',
placeholder: '0',
};
state = {
value: this.props.value,
};
componentDidUpdate(prevProps) {
const { value: prevPropsValue } = prevProps;
const { value: propsValue } = this.props;
const { value: stateValue } = this.state;
if (prevPropsValue !== propsValue && propsValue !== stateValue) {
this.setState({ value: propsValue });
}
}
handleFocus = () => {
this.unitInput.focus();
};
handleInputFocus = ({ target: { value } }) => {
if (value === '0') {
this.setState({ value: '' });
}
};
handleInputBlur = ({ target: { value } }) => {
if (value === '') {
this.setState({ value: '0' });
}
this.props.onBlur && this.props.onBlur(value);
};
handleChange = (event) => {
const { value: userInput } = event.target;
let value = userInput;
if (userInput.length && userInput.length > 1) {
value = removeLeadingZeroes(userInput);
}
this.setState({ value });
this.props.onChange(value);
};
getInputWidth(value) {
const valueString = String(value);
const valueLength = valueString.length || 1;
const decimalPointDeficit = valueString.match(/\./u) ? -0.5 : 0;
return `${valueLength + decimalPointDeficit + 0.5}ch`;
}
render() {
const {
error,
placeholder,
suffix,
actionComponent,
children,
dataTestId,
} = this.props;
const { value } = this.state;
return (
<div
className={classnames('unit-input', { 'unit-input--error': error })}
onClick={this.handleFocus}
>
<div className="unit-input__inputs">
<div className="unit-input__input-container">
<input
data-testid={dataTestId}
type="number"
dir="ltr"
className={classnames('unit-input__input')}
value={value}
placeholder={placeholder}
onChange={this.handleChange}
onBlur={this.handleInputBlur}
onFocus={this.handleInputFocus}
style={{ width: this.getInputWidth(value) }}
ref={(ref) => {
this.unitInput = ref;
}}
autoFocus
/>
{suffix ? <div className="unit-input__suffix">{suffix}</div> : null}
</div>
{children}
</div>
{actionComponent}
</div>
);
}
}