UNPKG

chayns-components

Version:

A set of beautiful React components for developing chayns® applications.

428 lines (412 loc) 13.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; var _clsx = _interopRequireDefault(require("clsx")); var _propTypes = _interopRequireDefault(require("prop-types")); var _react = _interopRequireWildcard(require("react")); var _AmountInput = _interopRequireDefault(require("./AmountInput")); var _ControlButton = _interopRequireDefault(require("./ControlButton")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /** * @component */ // region icon default values // default icon to add one step to the AmountControl const DEFAULT_PLUS_ICON = 'fa fa-plus'; // default remove icon when there are more than one item const DEFAULT_MINUS_ICON = 'fa fa-minus'; // default remove icon for the last item (value = 1) const DEFAULT_REMOVE_ICON = 'fa fa-minus'; // default remove icon when there is only one item available (max = 1) const DEFAULT_SINGLE_REMOVE_ICON = 'fa fa-check'; // endregion /** * The AmountControl is a three-segment control used to increase or decrease an * incremental value. */ class AmountControl extends _react.PureComponent { constructor(props) { super(props); this.onInput = value => { const { onInput } = this.props; let numberValue = 0; if (chayns.utils.isNumber(value)) { numberValue = value; } this.setState({ tempAmount: numberValue, tempValue: value }); if (onInput && (numberValue || numberValue >= 0)) { onInput(numberValue); } }; this.addItem = () => { const { amount, onAdd, max } = this.props; if (max && amount + 1 > max) { return; } if (onAdd) onAdd(); this.changeAmount(amount + 1); }; this.removeItem = () => { const { amount, onRemove, min, hasAlwaysControls } = this.props; if (min && amount - 1 < min) { return; } if (onRemove) onRemove(); if (amount > 0) { this.changeAmount(amount - 1); } else if (!hasAlwaysControls) { this.addItem(); } }; this.changeAmount = amount => { const { onChange, onInput, amount: oldAmount, disableAdd, disableRemove, min, max } = this.props; if (onInput) { onInput(amount); } if (onChange) { if (disableAdd && amount > oldAmount || disableRemove && amount < oldAmount || min && amount < min || max && amount > max) { this.setState({ tempValue: oldAmount, tempAmount: oldAmount }); return; } onChange(amount); } }; this.state = { tempAmount: props.amount, tempValue: props.amount }; } componentDidUpdate(prevProps) { const { amount } = this.props; if (prevProps.amount !== amount) { // eslint-disable-next-line react/no-did-update-set-state this.setState({ tempAmount: amount, tempValue: amount }); } } getRemoveIcon() { const { amount, icon, removeIcon, minusIcon, hasAlwaysControls, max } = this.props; const { tempAmount } = this.state; if (icon && !tempAmount && !hasAlwaysControls) { return icon; } if (tempAmount > 1 || amount > 1) { return minusIcon; } // the default removeIcon will become a trash-can when the max-value is 1 return removeIcon !== null && removeIcon !== void 0 ? removeIcon : max === 1 ? DEFAULT_SINGLE_REMOVE_ICON : DEFAULT_REMOVE_ICON; } /** * Checks whether the add button should be shown. * @returns {boolean} */ isAddButtonShown() { const { showAddButton, max } = this.props; // When the showAddButton prop is explicitly set, we will use the value if (showAddButton !== undefined) { return showAddButton; } // When using the default value (undefined) and the max prop is set to 1 // the add button should be removed (only the remove button will be displayed as trash-can) if (max === 1) { return false; } // when we do not have max set or it is greater than 1, we will use the default value (show the add button) return true; } /** * Checks whether the input element should be enabled * @returns {boolean} */ isInputEnabled() { const { disableInput, max, amount } = this.props; // When max and amount are both 1 even the disableInput-prop will be ignored if (max === 1 && amount === 1) { return false; } // When the disableInput-prop is manually set (not defaultValue: undefined) // this value has precedence over all default behaviour if (disableInput !== undefined) { return !disableInput; } // When the max value is only one, the input should be disabled if (max === 1) { return false; } // normally the input-field should be shown (default) return true; } render() { const { amount, buttonText, disabled, disableAdd, disableRemove, className, autoInput, buttonFormatHandler, showInput: showInputProp, icon, removeColor, addColor, iconColor, equalize, focusOnClick, contentWidth, stopPropagation, plusIcon, max, min, hasAlwaysControls } = this.props; const { tempAmount, tempValue } = this.state; const removeIconColor = icon && !tempAmount && !hasAlwaysControls ? iconColor : removeColor; const removeIconBackgroundColor = icon && !tempAmount && !hasAlwaysControls ? iconColor : addColor; return /*#__PURE__*/_react.default.createElement("div", { className: (0, _clsx.default)('cc__amount-control choosebutton', className, (amount > 0 && max !== 1 || hasAlwaysControls) && 'cc__amount-control--active', disabled && 'cc__amount-control--disabled'), onClick: amount === 1 && max === 1 ? this.removeItem : null }, /*#__PURE__*/_react.default.createElement(_ControlButton.default, { stopPropagation: stopPropagation, icon: this.getRemoveIcon(), onClick: amount === 1 && max === 1 ? null : this.removeItem, disabled: disabled || disableRemove || min && amount <= (min || 0), className: 'cc__amount-control__remove' + (amount > 0 || icon || hasAlwaysControls ? " cc__amount-control--icon" : ""), color: amount === 1 && max === 1 ? '#fff' : removeIconColor, backgroundColor: amount === 1 && max === 1 ? removeIconBackgroundColor : null }), /*#__PURE__*/_react.default.createElement(_AmountInput.default, { stopPropagation: stopPropagation && !(amount === 1 && max === 1), contentWidth: contentWidth, equalize: equalize, autoInput: autoInput, amount: amount, onChange: this.changeAmount, onInput: this.onInput, onAdd: this.addItem, buttonText: buttonText, disabled: disabled, disableInput: !this.isInputEnabled(), buttonFormatHandler: buttonFormatHandler, showInput: tempAmount !== 0 || tempValue !== 0 || showInputProp || hasAlwaysControls, tempAmount: tempAmount, tempValue: tempValue, focusOnClick: focusOnClick, max: max }), this.isAddButtonShown() && /*#__PURE__*/_react.default.createElement(_ControlButton.default, { stopPropagation: stopPropagation, icon: plusIcon, onClick: this.addItem, disabled: disabled || disableAdd || max && amount >= max, className: 'cc__amount-control__add' + (amount > 0 || hasAlwaysControls ? " cc__amount-control--icon" : ""), color: addColor })); } } exports.default = AmountControl; AmountControl.propTypes = { /** * This text will be shown in the button when the `amount`-prop is 0. */ buttonText: _propTypes.default.string, /** * This component works as a controlled input and this prop defines its * current state. */ amount: _propTypes.default.number, /** * This callback will be called when the amount is changed by the user. */ onChange: _propTypes.default.func, /** * Alias for onChange. */ onInput: _propTypes.default.func, /** * Called when the user clicks the increment-button. */ onAdd: _propTypes.default.func, /** * Called when the user clicks the decrement-button. */ onRemove: _propTypes.default.func, /** * Disables any interaction and switches to a disabled style. */ disabled: _propTypes.default.bool, /** * Disables the input field and forces the user to use the buttons to * control the value. */ disableInput: _propTypes.default.bool, /** * Disables the increment-button and disables the ability to increment the * value. */ disableAdd: _propTypes.default.bool, /** * Disables the decrement-button and disables the ability to decrement the * value. */ disableRemove: _propTypes.default.bool, /** * A classname that is applied to the wrapper of the component. */ className: _propTypes.default.string, /** * Shows an input field once the amount is greater than 10. */ autoInput: _propTypes.default.bool, /** * A function that returns the content of the button. */ buttonFormatHandler: _propTypes.default.func, /** * Whether to show the input. */ showInput: _propTypes.default.bool, /** * Whether the add button should be shown/rendered. */ showAddButton: _propTypes.default.bool, /** * Displays an icon on the left side of the button if the amount is 0. * Supply a FontAwesome-string like `"fa fa-plane"`. */ icon: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]), /** * The icon shown on the increment-button. */ plusIcon: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]), /** * The icon shown on the decrement-button. */ minusIcon: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]), /** * The icon the reset the amount to 0. */ removeIcon: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]), /** * The color of the remove icon. */ removeColor: _propTypes.default.string, /** * The color of the icon in the increment-button. */ addColor: _propTypes.default.string, /** * The color of the icon to the left of the button. */ iconColor: _propTypes.default.string, /** * Multiple `AmountControl` with the same `equalize`-prop will sync their * width. */ equalize: _propTypes.default.string, /** * Enables the input autofocus. */ focusOnClick: _propTypes.default.bool, /** * The width of the AmountControl content. */ contentWidth: _propTypes.default.number, /** * The minimum value of the AmountControl (the input field is not validated). */ min: _propTypes.default.number, /** * The maximum value of the AmountControl (the input field is not validated). */ max: _propTypes.default.number, /** * Stop propagation of click events to parent components. */ stopPropagation: _propTypes.default.bool, /** * Always show the increment and decrement buttons. */ hasAlwaysControls: _propTypes.default.bool }; AmountControl.defaultProps = { buttonText: null, amount: 0, onChange: null, onInput: null, onAdd: null, onRemove: null, disabled: false, disableAdd: false, disableRemove: false, className: '', autoInput: false, buttonFormatHandler: undefined, showInput: false, icon: null, removeColor: null, addColor: null, iconColor: null, equalize: null, focusOnClick: true, contentWidth: null, stopPropagation: false, min: null, max: null, plusIcon: DEFAULT_PLUS_ICON, minusIcon: DEFAULT_MINUS_ICON, removeIcon: undefined, hasAlwaysControls: false, disableInput: undefined, showAddButton: undefined }; AmountControl.displayName = 'AmountControl'; //# sourceMappingURL=AmountControl.js.map