import React from 'react'; import { View, StyleProp, StyleSheet, ViewStyle } from 'react-native'; import useControlledOrUncontrolled from '../../hooks/useControlledOrUncontrolled'; import type { Theme, DimensionValue } from '../../types'; import { withTheme } from '../../core/theming'; import { blockSizes } from '../../styles/styles'; import { clamp } from '../../utils'; import { TextInput, Button, ArrowIcon } from '../..'; type Props = { defaultValue?: number; disabled?: boolean; inputWidth?: DimensionValue; max?: number | null; min?: number | null; onChange?: (value: number) => void; step?: number; style?: StyleProp; theme: Theme; value?: number; variant?: 'default' | 'flat'; }; // TODO: allow to center input text horizontally // TODO: how are uncontrolled inputs handled in RN? const NumberInput = ({ defaultValue, disabled, inputWidth, max = null, min = null, onChange, step = 1, style = {}, theme, value, variant = 'default', ...rest }: Props) => { const [valueDerived, setValueState] = useControlledOrUncontrolled({ value, defaultValue, }); const handleClick = (val: number) => { const stateValue = parseFloat(valueDerived); const newValue = clamp( +parseFloat((stateValue + val).toString()).toFixed(2), min, max, ).toString(); setValueState(parseFloat(newValue)); if (onChange) { onChange(parseFloat(newValue)); } }; const valueDerivedNumber = parseFloat(valueDerived); const isDecrementDisabled = disabled || valueDerivedNumber === min; const isIncrementDisabled = disabled || valueDerivedNumber === max; const isFlat = variant === 'flat'; return ( ); }; const styles = StyleSheet.create({ wrapper: { display: 'flex', flexDirection: 'row', justifyContent: 'center', }, input: { marginHorizontal: 2, minWidth: blockSizes.md + 2, }, button: { width: blockSizes.md, }, buttonText: { fontSize: 24, }, }); export default withTheme(NumberInput);