UNPKG

@spark-web/float-input

Version:

--- title: Float Input storybookPath: forms-float-input--default isExperimentalPackage: true ---

173 lines (161 loc) 5.89 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _objectSpread = require('@babel/runtime/helpers/objectSpread2'); var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties'); var textInput = require('@spark-web/text-input'); var react = require('react'); var _slicedToArray = require('@babel/runtime/helpers/slicedToArray'); var numeral = require('numeral'); var jsxRuntime = require('react/jsx-runtime'); function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; } var numeral__default = /*#__PURE__*/_interopDefault(numeral); /** Ensure only valid values are passed to the consumer */ var isValid = function isValid(text) { var valid = /^\s*\$?-?[\d,]+(\.\d+)?\s*$/; return valid.test(text) && !isNaN(parse(text)); }; /** Strip invalid characters */ var normalise = function normalise(text) { return text.trim().replace(/^\$/, '').replace(/,/g, ''); }; /** Safe parse */ var parse = function parse(text) { return parseFloat(normalise(text)); }; /** Resolve leading decimal issues */ var padLeadingDecimal = function padLeadingDecimal(text) { if (text.startsWith('.')) { return "0".concat(text); } else if (text.startsWith('-.')) { return "-0".concat(text.substring(1)); } return text; }; /** Prepare the formatter */ var useFormat = function useFormat(fractionDigits) { return react.useCallback(function (val) { if (typeof val === 'undefined') { return ''; } if (typeof val === 'string' && !isValid(val)) { return val; } var pattern = fractionDigits ? "0,0.".concat('0'.repeat(fractionDigits)) : '0,0.[00000000]'; return numeral__default["default"](val).format(pattern); }, [fractionDigits]); }; var useFloatInput = function useFloatInput(_ref) { var fractionDigits = _ref.fractionDigits, consumerBlur = _ref.onBlur, consumerFocus = _ref.onFocus, controlledOnChange = _ref.onChange, controlledValue = _ref.value; if (Number.isNaN(controlledValue)) { throw new Error('NaN cannot be provided to numeric inputs.'); } var format = useFormat(fractionDigits); var isControlled = controlledValue !== undefined && controlledOnChange !== undefined; var _useState = react.useState(function () { return format(controlledValue); }), _useState2 = _slicedToArray(_useState, 2), internalValue = _useState2[0], setInternalValue = _useState2[1]; var uncontrolledHandlers = { onChange: react.useCallback(function (e) { var paddedText = padLeadingDecimal(e.currentTarget.value); setInternalValue(normalise(paddedText)); }, []), onBlur: useFocusHandler(consumerBlur, function () { setInternalValue(format(internalValue)); }), onFocus: useFocusHandler(consumerFocus, function () { setInternalValue(function (currentValue) { return normalise(currentValue); }); }), value: internalValue }; var controlledHandlers = { onChange: react.useCallback(function (e) { if (!isControlled) return; var paddedText = padLeadingDecimal(e.currentTarget.value); if (!e.currentTarget.value) { controlledOnChange(''); } else if (isValid(paddedText)) { controlledOnChange(parse(paddedText)); } else { controlledOnChange(normalise(paddedText)); } setInternalValue(normalise(paddedText)); }, [controlledOnChange, isControlled]), onBlur: useFocusHandler(consumerBlur, function () { if (!isControlled) return; if (typeof controlledValue === 'number' && fractionDigits) { controlledOnChange(parse(controlledValue.toFixed(fractionDigits))); } else { controlledOnChange(controlledValue !== null && controlledValue !== void 0 ? controlledValue : ''); } setInternalValue(format(internalValue)); }), onFocus: useFocusHandler(consumerFocus, function () { setInternalValue(function (currentValue) { return normalise(currentValue); }); }), value: internalValue }; return isControlled ? controlledHandlers : uncontrolledHandlers; }; var useFocusHandler = function useFocusHandler(consumerHandler, ourHandler) { return react.useCallback(function (event) { if (typeof consumerHandler === 'function') { consumerHandler(event); } if (!(event !== null && event !== void 0 && event.defaultPrevented)) { ourHandler(event); } }, [consumerHandler, ourHandler]); }; var _excluded = ["fractionDigits", "onBlur", "onFocus", "onChange", "value", "data", "placeholder", "children"]; var FloatInput = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) { var fractionDigits = _ref.fractionDigits, onBlur = _ref.onBlur, onFocus = _ref.onFocus, onChange = _ref.onChange, value = _ref.value, data = _ref.data, placeholder = _ref.placeholder, children = _ref.children, inputProps = _objectWithoutProperties(_ref, _excluded); var inputs = { fractionDigits: fractionDigits, onBlur: onBlur, onFocus: onFocus }; if (onChange !== undefined && value !== undefined) { inputs = _objectSpread(_objectSpread({}, inputs), {}, { onChange: onChange, value: value }); } var _useFloatInput = useFloatInput(inputs), floatOnBlur = _useFloatInput.onBlur, floatOnChange = _useFloatInput.onChange, floatOnFocus = _useFloatInput.onFocus, floatValue = _useFloatInput.value; return /*#__PURE__*/jsxRuntime.jsx(textInput.TextInput, _objectSpread(_objectSpread({}, inputProps), {}, { ref: forwardedRef, data: data, placeholder: placeholder, type: "text", inputMode: "decimal", onBlur: floatOnBlur, onChange: floatOnChange, onFocus: floatOnFocus, value: floatValue, children: children })); }); FloatInput.displayName = 'FloatInput'; exports.FloatInput = FloatInput;