diff --git a/src/components/BitcoinAmountInput.test.tsx b/src/components/BitcoinAmountInput.test.tsx
index aab58e3a..b46b6b06 100644
--- a/src/components/BitcoinAmountInput.test.tsx
+++ b/src/components/BitcoinAmountInput.test.tsx
@@ -95,4 +95,25 @@ describe('', () => {
expect(inputElement.dataset.displayUnit).toBe(undefined)
expect(inputElement.dataset.displayValue).toBe('')
})
+
+ it('amount 1.0 should be interpreted as 1 BTC', async () => {
+ setup({
+ label: 'test-label',
+ })
+ const inputElement = screen.getByLabelText('test-label')
+
+ await user.type(inputElement, '1.0')
+
+ expect(inputElement).toHaveFocus()
+ expect(inputElement.dataset.value).toBe('100000000')
+ expect(inputElement.dataset.displayUnit).toBe('BTC')
+ expect(inputElement.dataset.displayValue).toBe(`1.0`)
+
+ await user.tab()
+
+ expect(inputElement).not.toHaveFocus()
+ expect(inputElement.dataset.value).toBe('100000000')
+ expect(inputElement.dataset.displayUnit).toBe('BTC')
+ expect(inputElement.dataset.displayValue).toBe(`1.00 000 000`)
+ })
})
diff --git a/src/components/BitcoinAmountInput.tsx b/src/components/BitcoinAmountInput.tsx
index bca70df8..d4f565b0 100644
--- a/src/components/BitcoinAmountInput.tsx
+++ b/src/components/BitcoinAmountInput.tsx
@@ -61,6 +61,78 @@ const BitcoinAmountInput = forwardRef(
: undefined
}, [field, inputType])
+ const handleBlur = (e: React.FocusEvent) => {
+ setInputType({
+ type: 'text',
+ inputMode: 'decimal',
+ })
+
+ let displayValue = String(field.value?.value || '')
+ if (isValidNumber(field.value?.value)) {
+ displayValue = formatBtcDisplayValue(field.value!.value!)
+ }
+
+ form.setFieldValue(
+ field.name,
+ {
+ ...field.value,
+ displayValue,
+ },
+ false,
+ )
+ field.onBlur(e)
+ }
+
+ const handleChange = (e: React.ChangeEvent) => {
+ const rawUserInputOrEmpty = e.target.value ?? ''
+ const validNumberRegex = /^-?\d*\.?\d*$/
+ if (!validNumberRegex.test(rawUserInputOrEmpty)) {
+ return
+ }
+ const floatValueOrNan = parseFloat(rawUserInputOrEmpty)
+ if (!isValidNumber(floatValueOrNan)) {
+ form.setFieldValue(
+ field.name,
+ {
+ ...field.value,
+ value: null,
+ userRawInputValue: e.target.value,
+ displayValue: e.target.value,
+ },
+ true,
+ )
+ return
+ } else {
+ const value: number = floatValueOrNan
+ let numberValues: string | undefined
+ const unit =
+ rawUserInputOrEmpty.includes('.') && parseFloat(rawUserInputOrEmpty)
+ ? unitFromValue(String(rawUserInputOrEmpty))
+ : unitFromValue(String(value))
+ if (unit === 'BTC') {
+ const splitted = String(value).split('.')
+ const [integerPart, fractionalPart = ''] = splitted
+ const paddedFractionalPart = fractionalPart.padEnd(8, '0').substring(0, 8)
+ numberValues = `${integerPart}${paddedFractionalPart}`
+ } else {
+ numberValues = value.toLocaleString('en-US', {
+ maximumFractionDigits: 0,
+ useGrouping: false,
+ })
+ }
+
+ form.setFieldValue(
+ field.name,
+ {
+ value: parseInt(numberValues, 10),
+ userRawInputValue: e.target.value,
+ displayValue: e.target.value,
+ },
+ true,
+ )
+ }
+ }
+
return (
<>
@@ -77,7 +149,6 @@ const BitcoinAmountInput = forwardRef(
data-display-value={field.value?.displayValue}
name={field.name}
autoComplete="off"
- type={inputType.type}
inputMode={inputType.inputMode}
className={classNames('slashed-zeroes', className)}
value={
@@ -92,70 +163,8 @@ const BitcoinAmountInput = forwardRef(
onFocus={() => {
setInputType({ type: 'number' })
}}
- onBlur={(e) => {
- setInputType({
- type: 'text',
- inputMode: 'decimal',
- })
-
- let displayValue = String(field.value?.value || '')
- if (isValidNumber(field.value?.value)) {
- displayValue = formatBtcDisplayValue(field.value!.value!)
- }
-
- form.setFieldValue(
- field.name,
- {
- ...field.value,
- displayValue,
- },
- false,
- )
- field.onBlur(e)
- }}
- onChange={(e) => {
- const valueOrNan = parseFloat(e.target.value ?? '')
-
- if (!isValidNumber(valueOrNan)) {
- form.setFieldValue(
- field.name,
- {
- ...field.value,
- value: null,
- userRawInputValue: e.target.value,
- displayValue: e.target.value,
- },
- true,
- )
- return
- } else {
- const value: number = valueOrNan
-
- let numberValues: string | undefined
- const unit = unitFromValue(String(value))
- if (unit === 'BTC') {
- const splitted = String(value).split('.')
- const [integerPart, fractionalPart = ''] = splitted
- const paddedFractionalPart = fractionalPart.padEnd(8, '0').substring(0, 8)
- numberValues = `${integerPart}${paddedFractionalPart}`
- } else {
- numberValues = value.toLocaleString('en-US', {
- maximumFractionDigits: 0,
- useGrouping: false,
- })
- }
-
- form.setFieldValue(
- field.name,
- {
- value: parseInt(numberValues, 10),
- userRawInputValue: e.target.value,
- displayValue: e.target.value,
- },
- true,
- )
- }
- }}
+ onBlur={handleBlur}
+ onChange={handleChange}
/>
{children}