aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/components/unit-input/unit-input.component.js
diff options
context:
space:
mode:
Diffstat (limited to 'ui/app/components/unit-input/unit-input.component.js')
-rw-r--r--ui/app/components/unit-input/unit-input.component.js104
1 files changed, 104 insertions, 0 deletions
diff --git a/ui/app/components/unit-input/unit-input.component.js b/ui/app/components/unit-input/unit-input.component.js
new file mode 100644
index 000000000..f1ebf4d77
--- /dev/null
+++ b/ui/app/components/unit-input/unit-input.component.js
@@ -0,0 +1,104 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import classnames from 'classnames'
+import { removeLeadingZeroes } from '../send/send.utils'
+
+/**
+ * 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 = {
+ children: PropTypes.node,
+ error: PropTypes.bool,
+ onBlur: PropTypes.func,
+ onChange: PropTypes.func,
+ placeholder: PropTypes.string,
+ suffix: PropTypes.string,
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ }
+
+ static defaultProps = {
+ placeholder: '0',
+ }
+
+ constructor (props) {
+ super(props)
+
+ this.state = {
+ value: 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()
+ }
+
+ 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)
+ }
+
+ handleBlur = event => {
+ const { onBlur } = this.props
+ typeof onBlur === 'function' && onBlur(this.state.value)
+ }
+
+ getInputWidth (value) {
+ const valueString = String(value)
+ const valueLength = valueString.length || 1
+ const decimalPointDeficit = valueString.match(/\./) ? -0.5 : 0
+ return (valueLength + decimalPointDeficit + 0.75) + 'ch'
+ }
+
+ render () {
+ const { error, placeholder, suffix, children } = this.props
+ const { value } = this.state
+
+ return (
+ <div
+ className={classnames('unit-input', { 'unit-input--error': error })}
+ onClick={this.handleFocus}
+ >
+ <div className="unit-input__input-container">
+ <input
+ type="number"
+ className="unit-input__input"
+ value={value}
+ placeholder={placeholder}
+ onChange={this.handleChange}
+ onBlur={this.handleBlur}
+ style={{ width: this.getInputWidth(value) }}
+ ref={ref => { this.unitInput = ref }}
+ />
+ {
+ suffix && (
+ <div className="unit-input__suffix">
+ { suffix }
+ </div>
+ )
+ }
+ </div>
+ { children }
+ </div>
+ )
+ }
+}