Skip to content
This repository has been archived by the owner on Nov 17, 2023. It is now read-only.

Commit

Permalink
feat(components): add new AmountInput component
Browse files Browse the repository at this point in the history
Add a new AmountInput component to render an input field for entering
bitcoin denominated amounts. Has special handling for bitcoin / sats /
bits to ensure that only valid amounts can be entered and that the
formatting looks visually correct.
  • Loading branch information
DataCourier authored and mrfelton committed Aug 23, 2018
1 parent fb9c4b5 commit d51e39f
Show file tree
Hide file tree
Showing 4 changed files with 418 additions and 0 deletions.
164 changes: 164 additions & 0 deletions app/components/AmountInput/AmountInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
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)
}

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]*'
}
}
}

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 (
<input
id="amount"
onChange={this.handleChange}
onBlur={this.handleBlur}
onKeyDown={this.handleKeyDown}
readOnly={readOnly}
type="text"
required
value={amount}
pattern={this.rules.pattern}
placeholder={this.rules.placeholder}
/>
)
}
}

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
Empty file.
3 changes: 3 additions & 0 deletions app/components/AmountInput/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import AmountInput from './AmountInput'

export default AmountInput
Loading

0 comments on commit d51e39f

Please sign in to comment.