import React, { useState, useEffect } from 'react'; import { Grid, TextField, Select, MenuItem } from '@mui/material'; import TextFieldWithDesc from '@components/options/TextFieldWithDesc'; import Autocomplete from '@mui/material/Autocomplete'; import Qty from 'js-quantities'; // const siPrefixes: { [key: string]: number } = { '': 1, k: 1000, M: 1000000, G: 1000000000, T: 1000000000000, m: 0.001, u: 0.000001, n: 0.000000001, p: 0.000000000001 }; export default function NumericInputWithUnit(props: { value: { value: number; unit: string }; disabled?: boolean; disableChangingUnit?: boolean; onOwnChange: (value: { value: number; unit: string }, ...baseProps) => void; defaultPrefix?: string; }) { const [inputValue, setInputValue] = useState(props.value.value); const [prefix, setPrefix] = useState(props.defaultPrefix || ''); const [unit, setUnit] = useState(props.value.unit); const [unitOptions, setUnitOptions] = useState([]); const [disabled, setDisabled] = useState(props.disabled); const [disableChangingUnit, setDisableChangingUnit] = useState( props.disableChangingUnit ); useEffect(() => { setDisabled(props.disabled); setDisableChangingUnit(props.disableChangingUnit); }, [props.disabled, props.disableChangingUnit]); useEffect(() => { try { const kind = Qty(props.value.unit).kind(); const units = Qty.getUnits(kind); if (!units.includes(props.value.unit)) { units.push(props.value.unit); } setUnitOptions(units); } catch (error) { console.error('Invalid unit kind', error); } }, [props.value.unit]); useEffect(() => { setInputValue(props.value.value); setUnit(props.value.unit); }, [props.value]); const handleValueChange = (val: { value: number; unit: string }) => { const newValue = val.value; setInputValue(newValue); if (props.onOwnChange) { try { const qty = Qty(newValue * siPrefixes[prefix], unit).to(val.unit); props.onOwnChange({ unit: val.unit, value: qty.scalar }); } catch (error) { console.error('Conversion error', error); } } }; const handlePrefixChange = (newPrefix: string) => { const oldPrefixValue = siPrefixes[prefix]; const newPrefixValue = siPrefixes[newPrefix]; setPrefix(newPrefix); // Value does not change, it is just re-formatted for display // handleValueChange({ // value: (inputValue * oldPrefixValue) / newPrefixValue, // unit: unit // }); }; const handleUnitChange = (newUnit: string) => { if (!newUnit) return; const oldInputValue = inputValue; const oldUnit = unit; setUnit(newUnit); setPrefix(''); try { const convertedValue = Qty( oldInputValue * siPrefixes[prefix], oldUnit ).to(newUnit).scalar; setInputValue(convertedValue); } catch (error) { console.error('Unit conversion error', error); } if (props.onOwnChange) { try { const qty = Qty(inputValue, unit).to(newUnit); props.onOwnChange({ unit: newUnit, value: qty.scalar }); } catch (error) { console.error('Conversion error', error); } } }; return ( handleValueChange({ value: parseFloat(value), unit: unit }) } label="Value" /> ); }