import React from 'react' import PropTypes from 'prop-types' class AmountInput extends React.Component { constructor(props) { super(props) this.handleChange = this.handleChange.bind(this) this.handleBlur = this.handleBlur.bind(this) this.handleKeyDown = this.handleKeyDown.bind(this) this.textInput = React.createRef() } setRules() { const { currency } = this.props switch (currency) { case 'btc': this.rules = { precision: 8, placeholder: '0.00000000', pattern: '[0-9.]*' } break case 'bits': this.rules = { precision: 2, placeholder: '0.00', pattern: '[0-9.]*' } break case 'sats': this.rules = { precision: 0, placeholder: '00000000', pattern: '[0-9]*' } break default: this.rules = { precision: 2, pattern: '[0-9]*' } } } focusTextInput() { this.textInput.current.focus() } clearTextInput() { this.textInput.current.value = '' } parseNumber(_value) { let value = _value || '' if (typeof _value === 'string') { value = _value.replace(/[^0-9.]/g, '') } let integer = null let fractional = null if (value * 1.0 < 0) { value = '0.0' } // pearse integer and fractional value so that we can reproduce the same string value afterwards // [0, 0] === 0.0 // [0, ''] === 0. // [0, null] === 0 if (value.match(/^[0-9]*\.[0-9]*$/)) { ;[integer, fractional] = value.toString().split(/\./) if (!fractional) { fractional = '' } } else { integer = value } // Limit fractional precision to the correct number of decimal places. if (fractional && fractional.length > this.rules.precision) { fractional = fractional.substring(0, this.rules.precision) } return [integer, fractional] } formatValue(integer, fractional) { let value if (fractional && fractional.length > 0) { value = `${integer}.${fractional}` } else { // Empty string means `XYZ.` instead of just plain `XYZ`. if (fractional === '') { value = `${integer}.` } else { value = `${integer}` } } return value } handleChange(e) { let { value } = e.target const [integer, fractional] = this.parseNumber(value) value = this.formatValue(integer, fractional) const { onChangeEvent } = this.props if (onChangeEvent) { onChangeEvent(value) } } handleBlur(e) { let { value } = e.target const [integer, fractional] = this.parseNumber(value) value = this.formatValue(integer, fractional) const { onBlurEvent } = this.props if (onBlurEvent) { onBlurEvent(value) } } handleKeyDown(e) { // Do nothing if the user did select all key combo. if (e.metaKey && e.key === 'a') { return } // Do not allow multiple dots. let { value } = e.target if (e.key === '.') { if (value.search(/\./) >= 0) { e.preventDefault() } return } if (e.key.length === 1 && !e.key.match(/^[0-9.]$/)) { e.preventDefault() return } } render() { let { amount = '', readOnly } = this.props if (amount === null) { amount = '' } this.setRules() return ( ) } } AmountInput.propTypes = { amount: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), currency: PropTypes.string.isRequired, onChangeEvent: PropTypes.func, onBlurEvent: PropTypes.func, readOnly: PropTypes.bool } export default AmountInput