@xyo-network/react-shared 4.4.5 → 4.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.d.ts +30 -2
- package/dist/browser/index.mjs +207 -67
- package/dist/browser/index.mjs.map +1 -1
- package/package.json +14 -14
- package/src/components/bigint/FixedPointPopover.tsx +27 -0
- package/src/components/bigint/Input.stories.tsx +36 -0
- package/src/components/bigint/Input.ts +6 -0
- package/src/components/bigint/InputAdornment.tsx +44 -0
- package/src/components/bigint/TextField.tsx +103 -0
- package/src/components/bigint/index.ts +4 -0
- package/src/components/index.ts +1 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { FormControlProps, StandardTextFieldProps } from '@mui/material'
|
|
2
|
+
import {
|
|
3
|
+
FormControl, FormHelperText, TextField,
|
|
4
|
+
} from '@mui/material'
|
|
5
|
+
import type { FocusEventHandler } from 'react'
|
|
6
|
+
import React, {
|
|
7
|
+
useEffect, useMemo,
|
|
8
|
+
useState,
|
|
9
|
+
} from 'react'
|
|
10
|
+
|
|
11
|
+
import { FixedPointInputAdornment } from './InputAdornment.tsx'
|
|
12
|
+
|
|
13
|
+
export interface BigIntTextFieldProps extends StandardTextFieldProps {
|
|
14
|
+
onChangeFixedPoint?: (value: bigint) => void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const BigIntTextField: React.FC<BigIntTextFieldProps> = ({
|
|
18
|
+
helperText, onChangeFixedPoint, onChange, ...props
|
|
19
|
+
}) => {
|
|
20
|
+
const [value, setValue] = useState<number>(0)
|
|
21
|
+
const [rawValue, setRawValue] = useState<string>('')
|
|
22
|
+
const [fixedPoint, setFixedPoint] = useState(18)
|
|
23
|
+
const [error, setError] = useState<Error>()
|
|
24
|
+
|
|
25
|
+
const handleChange: FocusEventHandler<HTMLTextAreaElement> = (event) => {
|
|
26
|
+
// run standard callback
|
|
27
|
+
onChange?.(event)
|
|
28
|
+
// remove all alpha characters but allow decimals
|
|
29
|
+
const filteredValue = event.target.value.replaceAll(/[^\d.]/g, '')
|
|
30
|
+
// only allow one decimal point
|
|
31
|
+
if (filteredValue.split('.').length > 2) return
|
|
32
|
+
setRawValue(filteredValue)
|
|
33
|
+
|
|
34
|
+
// parse the raw filtered raw value
|
|
35
|
+
const value = Number.parseFloat(filteredValue || '0')
|
|
36
|
+
// if the value is NaN set it to 0
|
|
37
|
+
if (Number.isNaN(value)) setValue(0)
|
|
38
|
+
setValue(value)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const onFixedPointChange = (fixedPoint: number) => setFixedPoint(fixedPoint)
|
|
42
|
+
|
|
43
|
+
// on value or point changes, run the bigInt callback
|
|
44
|
+
const bigIntValue = useMemo(() => {
|
|
45
|
+
const fixedValue = value * (10 ** fixedPoint)
|
|
46
|
+
setError(undefined)
|
|
47
|
+
try {
|
|
48
|
+
return BigInt(fixedValue)
|
|
49
|
+
} catch (e) {
|
|
50
|
+
console.error(e)
|
|
51
|
+
setError(e as Error)
|
|
52
|
+
}
|
|
53
|
+
// run bigInt callback
|
|
54
|
+
}, [value, fixedPoint])
|
|
55
|
+
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (bigIntValue) onChangeFixedPoint?.(bigIntValue)
|
|
58
|
+
}, [bigIntValue])
|
|
59
|
+
|
|
60
|
+
// prevent the fixed point from being less than the number of decimal places
|
|
61
|
+
const minFixedPoint = rawValue.split('.')[1]?.length
|
|
62
|
+
|
|
63
|
+
const resolvedHelperText = useMemo(() => {
|
|
64
|
+
if (error) return 'Cannot convert to BigInt'
|
|
65
|
+
return helperText ?? 'Enter a number'
|
|
66
|
+
}, [helperText, error])
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<>
|
|
70
|
+
<TextField
|
|
71
|
+
onChange={handleChange}
|
|
72
|
+
type="string"
|
|
73
|
+
error={Boolean(error)}
|
|
74
|
+
slotProps={{
|
|
75
|
+
htmlInput: { pattern: '[0-9]*[.]?[0-9]*' },
|
|
76
|
+
input: {
|
|
77
|
+
startAdornment: (
|
|
78
|
+
<FixedPointInputAdornment
|
|
79
|
+
position="start"
|
|
80
|
+
fixedPoint={fixedPoint}
|
|
81
|
+
minFixedPoint={minFixedPoint}
|
|
82
|
+
onFixedPointChange={onFixedPointChange}
|
|
83
|
+
/>
|
|
84
|
+
),
|
|
85
|
+
},
|
|
86
|
+
}}
|
|
87
|
+
value={rawValue}
|
|
88
|
+
{...props}
|
|
89
|
+
/>
|
|
90
|
+
<FormHelperText>{resolvedHelperText}</FormHelperText>
|
|
91
|
+
</>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface InputWithFormControlProps extends FormControlProps {
|
|
96
|
+
textFieldProps?: BigIntTextFieldProps
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const WithFormControl: React.FC<InputWithFormControlProps> = ({ textFieldProps, ...props }) => (
|
|
100
|
+
<FormControl {...props}>
|
|
101
|
+
<BigIntTextField {...textFieldProps} />
|
|
102
|
+
</FormControl>
|
|
103
|
+
)
|