@spark-web/float-input
Version:
--- title: Float Input storybookPath: forms-float-input--default isExperimentalPackage: true ---
173 lines (161 loc) • 5.89 kB
JavaScript
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;
;