react-native-counter-input
Version:
Counter Input with fully customizable options for React Native
92 lines • 4.33 kB
JavaScript
import * as React from 'react';
import { TextInput, View, Image } from 'react-native';
import RNBounceable from '@freakycoder/react-native-bounceable';
import useStateWithCallback from './helpers/useStateWithCallback';
/**
* ? Local Imports
*/
import styles, { _container, _increaseButtonStyle, _decreaseButtonStyle, } from './CounterInput.style';
// ? White Assets
const plusIconWhite = require('./local-assets/plus-white.png');
const minusIconWhite = require('./local-assets/minus-white.png');
// ? Black Assets
const plusIconBlack = require('./local-assets/plus-black.png');
const minusIconBlack = require('./local-assets/minus-black.png');
const CounterInput = ({ style, initial, horizontal = false, reverseCounterButtons = false, backgroundColor = '#fff', width = horizontal ? 170 : undefined, borderRadius = 24, onChange, onIncreasePress, min, max, onChangeText, onDecreasePress, ImageComponent = Image, decreaseButtonBackgroundColor = '#0b349a', increaseButtonBackgroundColor = '#0b349a', }) => {
const [counter, setCounter] = useStateWithCallback(initial || 0);
// ? if true: it's for increase button, if false: it's for decrease button
const [isPressed, setPressed] = useStateWithCallback(true);
const handleOnIncreasePress = () => {
if (max === undefined || counter < max) {
setCounter(counter + 1, (newCounterValue) => {
onChange?.(newCounterValue);
setPressed(true, () => {
onIncreasePress && onIncreasePress(newCounterValue);
});
});
}
};
const handleOnDecreasePress = () => {
if (min === undefined || counter > min) {
setCounter(counter - 1, (newCounterValue) => {
onChange?.(newCounterValue);
setPressed(false, () => {
onDecreasePress && onDecreasePress(newCounterValue);
});
});
}
};
const handleOnChangeText = (text) => {
let input = parseInt(text, 10) || 0;
let oldNumber = counter;
if ((min !== undefined && input < min) ||
(max !== undefined && input > max)) {
setCounter(0, () => {
setPressed(false, () => {
setCounter(oldNumber, (newCounterValue) => {
onChangeText?.(newCounterValue);
onChange?.(newCounterValue);
});
});
});
}
else {
setCounter(input, (newCounterValue) => {
onChangeText?.(newCounterValue);
onChange?.(newCounterValue);
});
}
};
/* -------------------------------------------------------------------------- */
/* Render Methods */
/* -------------------------------------------------------------------------- */
const renderIncreaseCounter = () => {
return (<RNBounceable style={_increaseButtonStyle(isPressed, increaseButtonBackgroundColor)} bounceEffectIn={0.8} bounceVelocityIn={2} onPress={handleOnIncreasePress}>
<ImageComponent style={styles.buttonImageStyle} source={isPressed ? plusIconWhite : plusIconBlack}/>
</RNBounceable>);
};
const renderDecreaseCounter = () => {
return (<RNBounceable style={_decreaseButtonStyle(isPressed, decreaseButtonBackgroundColor)} bounceEffectIn={0.8} bounceVelocityIn={2} onPress={handleOnDecreasePress}>
<ImageComponent style={styles.buttonImageStyle} source={isPressed ? minusIconBlack : minusIconWhite}/>
</RNBounceable>);
};
const renderTextInput = () => {
return (<TextInput numberOfLines={1} keyboardType="numeric" style={styles.textInputStyle} onChangeText={handleOnChangeText}>
{counter}
</TextInput>);
};
return (<View style={[
_container(width, horizontal, backgroundColor, borderRadius),
style,
]}>
{reverseCounterButtons
? renderDecreaseCounter()
: renderIncreaseCounter()}
{renderTextInput()}
{reverseCounterButtons
? renderIncreaseCounter()
: renderDecreaseCounter()}
</View>);
};
export default CounterInput;
//# sourceMappingURL=CounterInput.js.map