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