@chayns-components/core
Version:
A set of beautiful React components for developing your own applications with chayns.
257 lines (254 loc) • 9.94 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = require("motion/react");
var _react2 = _interopRequireWildcard(require("react"));
var _amountControl = require("../../utils/amountControl");
var _useKeyboardFocusHighlighting = require("../../hooks/useKeyboardFocusHighlighting");
var _Icon = _interopRequireDefault(require("../icon/Icon"));
var _AmountControl = require("./AmountControl.styles");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const AmountControl = ({
amount,
icon,
iconColor,
isDisabled = false,
label,
maxAmount,
minAmount = 0,
onChange,
shouldEnableKeyboardHighlighting,
shouldForceLabel = false,
shouldShowAddIconOnMinAmount = false,
shouldShowIcon = true,
shouldShowWideInput = false,
step: stepProp = 1
}) => {
const shouldShowKeyboardHighlighting = (0, _useKeyboardFocusHighlighting.useKeyboardFocusHighlighting)(shouldEnableKeyboardHighlighting && !isDisabled);
const [amountValue, setAmountValue] = (0, _react2.useState)(minAmount);
const [inputValue, setInputValue] = (0, _react2.useState)(minAmount.toString());
const [displayState, setDisplayState] = (0, _react2.useState)('default');
const [isEditing, setIsEditing] = (0, _react2.useState)(false);
const step = (0, _react2.useMemo)(() => Number.isSafeInteger(stepProp) && stepProp >= 1 ? stepProp : 1, [stepProp]);
const inputRef = (0, _react2.useRef)(null);
/**
* This function controls the displayState
*/
(0, _react2.useEffect)(() => {
switch (true) {
case maxAmount && amountValue >= maxAmount:
setDisplayState('maxAmount');
return;
case amountValue > minAmount:
setDisplayState('normal');
return;
case amountValue === minAmount && amountValue >= 0 && shouldShowAddIconOnMinAmount:
setDisplayState('minAmount');
return;
default:
setDisplayState('default');
}
}, [amountValue, maxAmount, minAmount, shouldShowAddIconOnMinAmount]);
const hasFocus = (0, _react2.useMemo)(() => displayState !== 'default', [displayState]);
/**
* Function that sets the amountValue to the amount
*/
(0, _react2.useEffect)(() => {
if (typeof amount !== 'number') {
return;
}
setAmountValue((0, _amountControl.checkForValidAmount)({
amount,
maxAmount,
minAmount
}));
setInputValue((0, _amountControl.checkForValidAmount)({
amount,
maxAmount,
minAmount
}).toString());
}, [amount, maxAmount, minAmount]);
const handleAmountAdd = (0, _react2.useCallback)(() => {
setAmountValue(prevState => {
const newAmount = (0, _amountControl.checkForValidAmount)({
amount: prevState + step,
minAmount,
maxAmount
});
if (typeof onChange === 'function') {
onChange(newAmount);
}
return typeof amount === 'number' ? prevState : newAmount;
});
setInputValue(prevState => (0, _amountControl.checkForValidAmount)({
amount: Number(prevState) + step,
minAmount,
maxAmount
}).toString());
}, [amount, maxAmount, minAmount, onChange, step]);
const handleAmountRemove = (0, _react2.useCallback)(() => {
if (displayState === 'default') {
return;
}
setAmountValue(prevState => {
const newAmount = (0, _amountControl.checkForValidAmount)({
amount: prevState - step,
minAmount,
maxAmount
});
if (typeof onChange === 'function') {
onChange(newAmount);
}
return newAmount;
});
setInputValue(prevState => (0, _amountControl.checkForValidAmount)({
amount: Number(prevState) - step,
minAmount,
maxAmount
}).toString());
}, [displayState, maxAmount, minAmount, onChange, step]);
const handleFirstAmount = (0, _react2.useCallback)(() => {
if (isDisabled) {
return;
}
if (amountValue !== minAmount) {
return;
}
if (typeof onChange === 'function') {
onChange(minAmount + step);
}
setAmountValue(minAmount + step);
setInputValue((minAmount + step).toString());
}, [amountValue, isDisabled, minAmount, onChange, step]);
const handlePseudoInputClick = (0, _react2.useCallback)(() => {
if (isDisabled) {
return;
}
setIsEditing(true);
window.requestAnimationFrame(() => {
var _inputRef$current;
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus();
});
}, [isDisabled]);
const handleInputBlur = (0, _react2.useCallback)(() => {
const checkedValue = (0, _amountControl.checkForValidAmount)({
minAmount,
maxAmount,
amount: Math.round(Number(inputValue) / step) * step
});
setAmountValue(checkedValue);
setInputValue(checkedValue.toString());
setIsEditing(false);
if (typeof onChange === 'function') {
onChange(checkedValue);
}
if (inputValue === '') {
setInputValue(minAmount.toString());
}
}, [inputValue, maxAmount, minAmount, onChange, step]);
const handleInputChange = (0, _react2.useCallback)(event => {
const {
value
} = event.target;
const valueBefore = Number(value.replace(/\D/g, ''));
if (valueBefore < minAmount && minAmount === 0) {
setInputValue('0');
return;
}
setInputValue(valueBefore === 0 ? '' : valueBefore.toString());
}, [minAmount]);
let inputLabel = inputValue;
if (typeof label === 'string' && (displayState === 'default' || shouldForceLabel)) {
inputLabel = label;
}
const shouldShowPseudoInput = !isEditing && (inputValue === '0' || shouldForceLabel && typeof label === 'string' || inputLabel === label);
return (0, _react2.useMemo)(() => /*#__PURE__*/_react2.default.createElement(_AmountControl.StyledAmountControl, {
onClick: handleFirstAmount,
$isDisabled: isDisabled
}, /*#__PURE__*/_react2.default.createElement(_react.AnimatePresence, {
initial: false
}, ['normal'].includes(displayState) && /*#__PURE__*/_react2.default.createElement(_AmountControl.StyledMotionAmountControlButton, {
$shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting,
key: "left_button",
initial: {
width: 0,
opacity: 0,
padding: 0
},
animate: {
width: 40,
opacity: 1,
padding: 0
},
exit: {
width: 0,
opacity: 0,
padding: 0
},
transition: {
duration: 0.2,
type: 'tween'
},
onClick: handleAmountRemove,
disabled: isDisabled || amountValue !== 0 && amountValue <= minAmount,
$isDisabled: isDisabled || amountValue !== 0 && amountValue <= minAmount
}, /*#__PURE__*/_react2.default.createElement(_Icon.default, {
icons: ['fa fa-minus'],
size: 14,
color: "white"
}))), /*#__PURE__*/_react2.default.createElement(_AmountControl.StyledInputWrapper, null, shouldShowPseudoInput ? /*#__PURE__*/_react2.default.createElement(_AmountControl.StyledAmountControlPseudoInput, {
onClick: handlePseudoInputClick,
$shouldShowWideInput: shouldShowWideInput,
$shouldShowRightIcon: !['maxAmount'].includes(displayState)
}, inputLabel) : /*#__PURE__*/_react2.default.createElement(_AmountControl.StyledAmountControlInput, {
ref: inputRef,
$displayState: displayState,
$shouldShowIcon: shouldShowIcon,
$shouldShowWideInput: shouldShowWideInput,
$hasFocus: hasFocus,
$shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting,
disabled: isDisabled,
onFocus: () => setIsEditing(true),
onBlur: handleInputBlur,
onChange: handleInputChange,
value: inputLabel
})), /*#__PURE__*/_react2.default.createElement(_react.AnimatePresence, {
initial: false
}, /*#__PURE__*/_react2.default.createElement(_AmountControl.StyledMotionAmountControlButton, {
$shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting,
key: "right_button",
initial: {
width: 0,
opacity: 0,
padding: 0
},
animate: {
width: 40,
opacity: 1,
padding: 0
},
exit: {
width: 0,
opacity: 0,
padding: 0
},
transition: {
duration: 0.2,
type: 'tween'
},
$color: displayState === 'maxAmount' ? 'rgb(32, 198, 90)' : undefined,
onClick: displayState === 'maxAmount' ? handleAmountRemove : handleAmountAdd,
disabled: isDisabled || (maxAmount ? amountValue >= maxAmount : false),
$isDisabled: isDisabled || (maxAmount ? amountValue >= maxAmount : false)
}, /*#__PURE__*/_react2.default.createElement(_Icon.default, {
icons: !['normal'].includes(displayState) && icon ? [displayState === 'maxAmount' ? 'fa fa-check' : icon] : [displayState === 'maxAmount' ? 'fa fa-check' : 'fa fa-plus'],
size: 14,
color: iconColor ?? 'white'
})))), [amountValue, displayState, handleAmountAdd, handleAmountRemove, handleFirstAmount, handleInputBlur, handleInputChange, handlePseudoInputClick, hasFocus, icon, iconColor, inputLabel, isDisabled, maxAmount, minAmount, shouldShowIcon, shouldShowKeyboardHighlighting, shouldShowPseudoInput, shouldShowWideInput]);
};
AmountControl.displayName = 'AmountControl';
var _default = exports.default = AmountControl;
//# sourceMappingURL=AmountControl.js.map