Browse Source

Improve InputCurrency

- you have more control on what you type, no more weird "empty input" cases
- it prevents to type more digits than the currency allows of magnitude
- it do everything to prevent you from typing weird things
master
Gaëtan Renaudeau 7 years ago
parent
commit
2d77bf0da9
  1. 85
      src/components/base/InputCurrency/index.js

85
src/components/base/InputCurrency/index.js

@ -6,7 +6,6 @@ import styled from 'styled-components'
import { formatCurrencyUnit } from '@ledgerhq/live-common/lib/helpers/currencies'
import noop from 'lodash/noop'
import isNaN from 'lodash/isNaN'
import Box from 'components/base/Box'
import Input from 'components/base/Input'
@ -14,6 +13,43 @@ import Select from 'components/base/LegacySelect'
import type { Unit } from '@ledgerhq/live-common/lib/types'
// TODO move this back to live common
const numbers = '0123456789'
const sanitizeValueString = (
unit: Unit,
valueString: string,
): {
display: string,
value: string,
} => {
let display = ''
let value = ''
let decimals = -1
for (let i = 0; i < valueString.length; i++) {
const c = valueString[i]
if (numbers.indexOf(c) !== -1) {
if (decimals >= 0) {
decimals++
if (decimals > unit.magnitude) break
value += c
display += c
} else if (value !== '0') {
value += c
display += c
}
} else if (decimals === -1 && (c === ',' || c === '.')) {
if (i === 0) display = '0'
decimals = 0
display += '.'
}
}
for (let i = decimals; i < unit.magnitude; ++i) {
value += '0'
}
if (!value) value = '0'
return { display, value }
}
function format(unit: Unit, value: number, { isFocused, showAllDigits, subMagnitude }) {
// FIXME do we need locale for the input too ?
return formatCurrencyUnit(unit, value, {
@ -81,9 +117,10 @@ class InputCurrency extends PureComponent<Props, State> {
componentWillReceiveProps(nextProps: Props) {
const { value, showAllDigits, unit } = this.props
const needsToBeReformatted =
value !== nextProps.value ||
showAllDigits !== nextProps.showAllDigits ||
unit !== nextProps.unit
!this.state.isFocused &&
(value !== nextProps.value ||
showAllDigits !== nextProps.showAllDigits ||
unit !== nextProps.unit)
if (needsToBeReformatted) {
const { isFocused } = this.state
this.setState({
@ -100,31 +137,13 @@ class InputCurrency extends PureComponent<Props, State> {
}
handleChange = (v: string) => {
// FIXME this is to refactor. this is hacky and don't cover everything..
v = v.toString().replace(/,/g, '.')
// allow to type directly `.` in input to have `0.`
if (v.startsWith('.')) {
v = `0${v}`
}
// forbid multiple 0 at start
if (v === '' || v.startsWith('00')) {
const { onChange, unit } = this.props
onChange(0, unit)
this.setState({ displayValue: '' })
return
}
// Check if value is valid Number
const asNumber = parseFloat(v)
if (isNaN(asNumber) || !isFinite(asNumber) || asNumber < 0) {
return
const { onChange, unit, value } = this.props
const r = sanitizeValueString(unit, v)
const satoshiValue = parseInt(r.value, 10)
if (value !== satoshiValue) {
onChange(satoshiValue, unit)
}
this.emitOnChange(v)
this.setState({ displayValue: v || '' })
this.setState({ displayValue: r.display })
}
handleBlur = () => {
@ -148,16 +167,6 @@ class InputCurrency extends PureComponent<Props, State> {
})
}
emitOnChange = (v: string) => {
const { onChange, unit } = this.props
const { displayValue } = this.state
if (displayValue.toString() !== v.toString()) {
const satoshiValue = Number(v) * 10 ** unit.magnitude
onChange(satoshiValue, unit)
}
}
renderItem = item => item.code
renderSelected = item => <Currency>{item.code}</Currency>

Loading…
Cancel
Save