1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
4 |
|
5 | var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
6 | var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
|
7 | var textInput = require('@spark-web/text-input');
|
8 | var react = require('react');
|
9 | var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
|
10 | var numeral = require('numeral');
|
11 | var jsxRuntime = require('react/jsx-runtime');
|
12 |
|
13 | function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
14 |
|
15 | var numeral__default = _interopDefault(numeral);
|
16 |
|
17 |
|
18 | var isValid = function isValid(text) {
|
19 | var valid = /^\s*\$?-?[\d,]+(\.\d+)?\s*$/;
|
20 | return valid.test(text) && !isNaN(parse(text));
|
21 | };
|
22 |
|
23 |
|
24 | var normalise = function normalise(text) {
|
25 | return text.trim().replace(/^\$/, '').replace(/,/g, '');
|
26 | };
|
27 |
|
28 |
|
29 | var parse = function parse(text) {
|
30 | return parseFloat(normalise(text));
|
31 | };
|
32 |
|
33 |
|
34 | var padLeadingDecimal = function padLeadingDecimal(text) {
|
35 | if (text.startsWith('.')) {
|
36 | return "0".concat(text);
|
37 | } else if (text.startsWith('-.')) {
|
38 | return "-0".concat(text.substring(1));
|
39 | }
|
40 | return text;
|
41 | };
|
42 |
|
43 |
|
44 | var useFormat = function useFormat(fractionDigits) {
|
45 | return react.useCallback(function (val) {
|
46 | if (typeof val === 'undefined') {
|
47 | return '';
|
48 | }
|
49 | if (typeof val === 'string' && !isValid(val)) {
|
50 | return val;
|
51 | }
|
52 | var pattern = fractionDigits ? "0,0.".concat('0'.repeat(fractionDigits)) : '0,0.[00000000]';
|
53 | return numeral__default["default"](val).format(pattern);
|
54 | }, [fractionDigits]);
|
55 | };
|
56 | var useFloatInput = function useFloatInput(_ref) {
|
57 | var fractionDigits = _ref.fractionDigits,
|
58 | consumerBlur = _ref.onBlur,
|
59 | consumerFocus = _ref.onFocus,
|
60 | controlledOnChange = _ref.onChange,
|
61 | controlledValue = _ref.value;
|
62 | if (Number.isNaN(controlledValue)) {
|
63 | throw new Error('NaN cannot be provided to numeric inputs.');
|
64 | }
|
65 | var format = useFormat(fractionDigits);
|
66 | var isControlled = controlledValue !== undefined && controlledOnChange !== undefined;
|
67 | var _useState = react.useState(function () {
|
68 | return format(controlledValue);
|
69 | }),
|
70 | _useState2 = _slicedToArray(_useState, 2),
|
71 | internalValue = _useState2[0],
|
72 | setInternalValue = _useState2[1];
|
73 | var uncontrolledHandlers = {
|
74 | onChange: react.useCallback(function (e) {
|
75 | var paddedText = padLeadingDecimal(e.currentTarget.value);
|
76 | setInternalValue(normalise(paddedText));
|
77 | }, []),
|
78 | onBlur: useFocusHandler(consumerBlur, function () {
|
79 | setInternalValue(format(internalValue));
|
80 | }),
|
81 | onFocus: useFocusHandler(consumerFocus, function () {
|
82 | setInternalValue(function (currentValue) {
|
83 | return normalise(currentValue);
|
84 | });
|
85 | }),
|
86 | value: internalValue
|
87 | };
|
88 | var controlledHandlers = {
|
89 | onChange: react.useCallback(function (e) {
|
90 | if (!isControlled) return;
|
91 | var paddedText = padLeadingDecimal(e.currentTarget.value);
|
92 | if (!e.currentTarget.value) {
|
93 | controlledOnChange('');
|
94 | } else if (isValid(paddedText)) {
|
95 | controlledOnChange(parse(paddedText));
|
96 | } else {
|
97 | controlledOnChange(normalise(paddedText));
|
98 | }
|
99 | setInternalValue(normalise(paddedText));
|
100 | }, [controlledOnChange, isControlled]),
|
101 | onBlur: useFocusHandler(consumerBlur, function () {
|
102 | if (!isControlled) return;
|
103 | if (typeof controlledValue === 'number' && fractionDigits) {
|
104 | controlledOnChange(parse(controlledValue.toFixed(fractionDigits)));
|
105 | } else {
|
106 | controlledOnChange(controlledValue !== null && controlledValue !== void 0 ? controlledValue : '');
|
107 | }
|
108 | setInternalValue(format(internalValue));
|
109 | }),
|
110 | onFocus: useFocusHandler(consumerFocus, function () {
|
111 | setInternalValue(function (currentValue) {
|
112 | return normalise(currentValue);
|
113 | });
|
114 | }),
|
115 | value: internalValue
|
116 | };
|
117 | return isControlled ? controlledHandlers : uncontrolledHandlers;
|
118 | };
|
119 | var useFocusHandler = function useFocusHandler(consumerHandler, ourHandler) {
|
120 | return react.useCallback(function (event) {
|
121 | if (typeof consumerHandler === 'function') {
|
122 | consumerHandler(event);
|
123 | }
|
124 | if (!(event !== null && event !== void 0 && event.defaultPrevented)) {
|
125 | ourHandler(event);
|
126 | }
|
127 | }, [consumerHandler, ourHandler]);
|
128 | };
|
129 |
|
130 | var _excluded = ["fractionDigits", "onBlur", "onFocus", "onChange", "value", "data", "placeholder", "children"];
|
131 | var FloatInput = react.forwardRef(function (_ref, forwardedRef) {
|
132 | var fractionDigits = _ref.fractionDigits,
|
133 | onBlur = _ref.onBlur,
|
134 | onFocus = _ref.onFocus,
|
135 | onChange = _ref.onChange,
|
136 | value = _ref.value,
|
137 | data = _ref.data,
|
138 | placeholder = _ref.placeholder,
|
139 | children = _ref.children,
|
140 | inputProps = _objectWithoutProperties(_ref, _excluded);
|
141 | var inputs = {
|
142 | fractionDigits: fractionDigits,
|
143 | onBlur: onBlur,
|
144 | onFocus: onFocus
|
145 | };
|
146 | if (onChange !== undefined && value !== undefined) {
|
147 | inputs = _objectSpread(_objectSpread({}, inputs), {}, {
|
148 | onChange: onChange,
|
149 | value: value
|
150 | });
|
151 | }
|
152 | var _useFloatInput = useFloatInput(inputs),
|
153 | floatOnBlur = _useFloatInput.onBlur,
|
154 | floatOnChange = _useFloatInput.onChange,
|
155 | floatOnFocus = _useFloatInput.onFocus,
|
156 | floatValue = _useFloatInput.value;
|
157 | return jsxRuntime.jsx(textInput.TextInput, _objectSpread(_objectSpread({}, inputProps), {}, {
|
158 | ref: forwardedRef,
|
159 | data: data,
|
160 | placeholder: placeholder,
|
161 | type: "text",
|
162 | inputMode: "decimal",
|
163 | onBlur: floatOnBlur,
|
164 | onChange: floatOnChange,
|
165 | onFocus: floatOnFocus,
|
166 | value: floatValue,
|
167 | children: children
|
168 | }));
|
169 | });
|
170 | FloatInput.displayName = 'FloatInput';
|
171 |
|
172 | exports.FloatInput = FloatInput;
|