@react-stately/numberfield 3.0.2 → 3.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -1,202 +1,200 @@
1
- var {
2
- useCallback,
3
- useEffect,
4
- useMemo,
5
- useRef,
6
- useState
7
- } = require("react");
1
+ var $cmJn2$reactstatelyutils = require("@react-stately/utils");
2
+ var $cmJn2$internationalizednumber = require("@internationalized/number");
3
+ var $cmJn2$react = require("react");
8
4
 
9
- var {
10
- NumberFormatter,
11
- NumberParser
12
- } = require("@internationalized/number");
13
-
14
- var {
15
- clamp,
16
- snapValueToStep,
17
- useControlledState
18
- } = require("@react-stately/utils");
19
-
20
- var _babelRuntimeHelpersExtends = $parcel$interopDefault(require("@babel/runtime/helpers/extends"));
21
-
22
- function $parcel$interopDefault(a) {
23
- return a && a.__esModule ? a.default : a;
24
- }
25
-
26
- /**
27
- * Provides state management for a number field component. Number fields allow users to enter a number,
28
- * and increment or decrement the value using stepper buttons.
29
- */
30
- function useNumberFieldState(props) {
31
- let {
32
- minValue,
33
- maxValue,
34
- step,
35
- formatOptions,
36
- value,
37
- defaultValue,
38
- onChange,
39
- locale,
40
- isDisabled,
41
- isReadOnly
42
- } = props;
43
- let [numberValue, setNumberValue] = useControlledState(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);
44
- let [inputValue, setInputValue] = useState(() => isNaN(numberValue) ? '' : new NumberFormatter(locale, formatOptions).format(numberValue));
45
- let numberParser = useMemo(() => new NumberParser(locale, formatOptions), [locale, formatOptions]);
46
- let numberingSystem = useMemo(() => numberParser.getNumberingSystem(inputValue), [numberParser, inputValue]);
47
- let formatter = useMemo(() => new NumberFormatter(locale, _babelRuntimeHelpersExtends({}, formatOptions, {
48
- numberingSystem
49
- })), [locale, formatOptions, numberingSystem]);
50
- let intlOptions = useMemo(() => formatter.resolvedOptions(), [formatter]);
51
- let format = useCallback(value => isNaN(value) ? '' : formatter.format(value), [formatter]);
52
- let clampStep = !isNaN(step) ? step : 1;
53
-
54
- if (intlOptions.style === 'percent' && isNaN(step)) {
55
- clampStep = 0.01;
56
- } // Update the input value when the number value or format options change. This is done
57
- // in a useEffect so that the controlled behavior is correct and we only update the
58
- // textfield after prop changes.
59
-
60
-
61
- useEffect(() => {
62
- setInputValue(format(numberValue));
63
- }, [numberValue, locale, formatOptions]); // Store last parsed value in a ref so it can be used by increment/decrement below
64
-
65
- let parsedValue = useMemo(() => numberParser.parse(inputValue), [numberParser, inputValue]);
66
- let parsed = useRef(0);
67
- parsed.current = parsedValue;
68
-
69
- let commit = () => {
70
- // Set to empty state if input value is empty
71
- if (!inputValue.length) {
72
- setNumberValue(NaN);
73
- setInputValue(value === undefined ? '' : format(numberValue));
5
+ function $parcel$exportWildcard(dest, source) {
6
+ Object.keys(source).forEach(function(key) {
7
+ if (key === 'default' || key === '__esModule' || dest.hasOwnProperty(key)) {
74
8
  return;
75
- } // if it failed to parse, then reset input to formatted version of current number
76
-
77
-
78
- if (isNaN(parsed.current)) {
79
- setInputValue(format(numberValue));
80
- return;
81
- } // Clamp to min and max, round to the nearest step, and round to specified number of digits
82
-
83
-
84
- let clampedValue;
85
-
86
- if (isNaN(step)) {
87
- clampedValue = clamp(parsed.current, minValue, maxValue);
88
- } else {
89
- clampedValue = snapValueToStep(parsed.current, minValue, maxValue, step);
90
- }
91
-
92
- clampedValue = numberParser.parse(format(clampedValue));
93
- setNumberValue(clampedValue); // in a controlled state, the numberValue won't change, so we won't go back to our old input without help
94
-
95
- setInputValue(format(value === undefined ? clampedValue : numberValue));
96
- };
97
-
98
- let safeNextStep = (operation, minMax) => {
99
- let prev = parsed.current;
100
-
101
- if (isNaN(prev)) {
102
- // if the input is empty, start from the min/max value when incrementing/decrementing,
103
- // or zero if there is no min/max value defined.
104
- let newValue = isNaN(minMax) ? 0 : minMax;
105
- return snapValueToStep(newValue, minValue, maxValue, clampStep);
106
- } else {
107
- // otherwise, first snap the current value to the nearest step. if it moves in the direction
108
- // we're going, use that value, otherwise add the step and snap that value.
109
- let newValue = snapValueToStep(prev, minValue, maxValue, clampStep);
110
-
111
- if (operation === '+' && newValue > prev || operation === '-' && newValue < prev) {
112
- return newValue;
113
- }
114
-
115
- return snapValueToStep($bb3f0c77930f1734ecd987a3e5d3aa28$var$handleDecimalOperation(operation, prev, clampStep), minValue, maxValue, clampStep);
116
9
  }
117
- };
118
10
 
119
- let increment = () => {
120
- setNumberValue(previousValue => {
121
- let newValue = safeNextStep('+', minValue); // if we've arrived at the same value that was previously in the state, the
122
- // input value should be updated to match
123
- // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
124
- // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
125
-
126
- if (newValue === previousValue) {
127
- setInputValue(format(newValue));
11
+ Object.defineProperty(dest, key, {
12
+ enumerable: true,
13
+ get: function get() {
14
+ return source[key];
128
15
  }
129
-
130
- return newValue;
131
16
  });
132
- };
133
-
134
- let decrement = () => {
135
- setNumberValue(previousValue => {
136
- let newValue = safeNextStep('-', maxValue);
17
+ });
137
18
 
138
- if (newValue === previousValue) {
139
- setInputValue(format(newValue));
140
- }
141
-
142
- return newValue;
143
- });
144
- };
145
-
146
- let incrementToMax = () => {
147
- if (maxValue != null) {
148
- setNumberValue(snapValueToStep(maxValue, minValue, maxValue, clampStep));
19
+ return dest;
20
+ }
21
+ function $parcel$export(e, n, v, s) {
22
+ Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
23
+ }
24
+ var $e18a693eeaf9c060$exports = {};
25
+
26
+ $parcel$export($e18a693eeaf9c060$exports, "useNumberFieldState", () => $e18a693eeaf9c060$export$7f629e9dc1ecf37c);
27
+
28
+
29
+
30
+ function $e18a693eeaf9c060$export$7f629e9dc1ecf37c(props) {
31
+ let { minValue: minValue , maxValue: maxValue , step: step , formatOptions: formatOptions , value: value1 , defaultValue: defaultValue , onChange: onChange , locale: locale , isDisabled: isDisabled , isReadOnly: isReadOnly } = props;
32
+ let [numberValue, setNumberValue] = $cmJn2$reactstatelyutils.useControlledState(value1, isNaN(defaultValue) ? NaN : defaultValue, onChange);
33
+ let [inputValue, setInputValue] = $cmJn2$react.useState(()=>isNaN(numberValue) ? '' : new $cmJn2$internationalizednumber.NumberFormatter(locale, formatOptions).format(numberValue)
34
+ );
35
+ let numberParser = $cmJn2$react.useMemo(()=>new $cmJn2$internationalizednumber.NumberParser(locale, formatOptions)
36
+ , [
37
+ locale,
38
+ formatOptions
39
+ ]);
40
+ let numberingSystem = $cmJn2$react.useMemo(()=>numberParser.getNumberingSystem(inputValue)
41
+ , [
42
+ numberParser,
43
+ inputValue
44
+ ]);
45
+ let formatter = $cmJn2$react.useMemo(()=>new $cmJn2$internationalizednumber.NumberFormatter(locale, {
46
+ ...formatOptions,
47
+ numberingSystem: numberingSystem
48
+ })
49
+ , [
50
+ locale,
51
+ formatOptions,
52
+ numberingSystem
53
+ ]);
54
+ let intlOptions = $cmJn2$react.useMemo(()=>formatter.resolvedOptions()
55
+ , [
56
+ formatter
57
+ ]);
58
+ let format = $cmJn2$react.useCallback((value)=>isNaN(value) ? '' : formatter.format(value)
59
+ , [
60
+ formatter
61
+ ]);
62
+ let clampStep = !isNaN(step) ? step : 1;
63
+ if (intlOptions.style === 'percent' && isNaN(step)) clampStep = 0.01;
64
+ // Update the input value when the number value or format options change. This is done
65
+ // in a useEffect so that the controlled behavior is correct and we only update the
66
+ // textfield after prop changes.
67
+ let prevValue = $cmJn2$react.useRef(numberValue);
68
+ let prevLocale = $cmJn2$react.useRef(locale);
69
+ let prevFormatOptions = $cmJn2$react.useRef(formatOptions);
70
+ if (!Object.is(numberValue, prevValue.current) || locale !== prevLocale.current || formatOptions !== prevFormatOptions.current) {
71
+ setInputValue(format(numberValue));
72
+ prevValue.current = numberValue;
73
+ prevLocale.current = locale;
74
+ prevFormatOptions.current = formatOptions;
149
75
  }
150
- };
151
-
152
- let decrementToMin = () => {
153
- if (minValue != null) {
154
- setNumberValue(minValue);
76
+ // Store last parsed value in a ref so it can be used by increment/decrement below
77
+ let parsedValue = $cmJn2$react.useMemo(()=>numberParser.parse(inputValue)
78
+ , [
79
+ numberParser,
80
+ inputValue
81
+ ]);
82
+ let parsed = $cmJn2$react.useRef(0);
83
+ parsed.current = parsedValue;
84
+ let commit = ()=>{
85
+ // Set to empty state if input value is empty
86
+ if (!inputValue.length) {
87
+ setNumberValue(NaN);
88
+ setInputValue(value1 === undefined ? '' : format(numberValue));
89
+ return;
90
+ }
91
+ // if it failed to parse, then reset input to formatted version of current number
92
+ if (isNaN(parsed.current)) {
93
+ setInputValue(format(numberValue));
94
+ return;
95
+ }
96
+ // Clamp to min and max, round to the nearest step, and round to specified number of digits
97
+ let clampedValue;
98
+ if (isNaN(step)) clampedValue = $cmJn2$reactstatelyutils.clamp(parsed.current, minValue, maxValue);
99
+ else clampedValue = $cmJn2$reactstatelyutils.snapValueToStep(parsed.current, minValue, maxValue, step);
100
+ clampedValue = numberParser.parse(format(clampedValue));
101
+ setNumberValue(clampedValue);
102
+ // in a controlled state, the numberValue won't change, so we won't go back to our old input without help
103
+ setInputValue(format(value1 === undefined ? clampedValue : numberValue));
104
+ };
105
+ let safeNextStep = (operation, minMax)=>{
106
+ let prev = parsed.current;
107
+ if (isNaN(prev)) {
108
+ // if the input is empty, start from the min/max value when incrementing/decrementing,
109
+ // or zero if there is no min/max value defined.
110
+ let newValue = isNaN(minMax) ? 0 : minMax;
111
+ return $cmJn2$reactstatelyutils.snapValueToStep(newValue, minValue, maxValue, clampStep);
112
+ } else {
113
+ // otherwise, first snap the current value to the nearest step. if it moves in the direction
114
+ // we're going, use that value, otherwise add the step and snap that value.
115
+ let newValue = $cmJn2$reactstatelyutils.snapValueToStep(prev, minValue, maxValue, clampStep);
116
+ if (operation === '+' && newValue > prev || operation === '-' && newValue < prev) return newValue;
117
+ return $cmJn2$reactstatelyutils.snapValueToStep($e18a693eeaf9c060$var$handleDecimalOperation(operation, prev, clampStep), minValue, maxValue, clampStep);
118
+ }
119
+ };
120
+ let increment = ()=>{
121
+ let newValue = safeNextStep('+', minValue);
122
+ // if we've arrived at the same value that was previously in the state, the
123
+ // input value should be updated to match
124
+ // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
125
+ // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
126
+ if (newValue === numberValue) setInputValue(format(newValue));
127
+ setNumberValue(newValue);
128
+ };
129
+ let decrement = ()=>{
130
+ let newValue = safeNextStep('-', maxValue);
131
+ if (newValue === numberValue) setInputValue(format(newValue));
132
+ setNumberValue(newValue);
133
+ };
134
+ let incrementToMax = ()=>{
135
+ if (maxValue != null) setNumberValue($cmJn2$reactstatelyutils.snapValueToStep(maxValue, minValue, maxValue, clampStep));
136
+ };
137
+ let decrementToMin = ()=>{
138
+ if (minValue != null) setNumberValue(minValue);
139
+ };
140
+ let canIncrement = $cmJn2$react.useMemo(()=>!isDisabled && !isReadOnly && (isNaN(parsedValue) || isNaN(maxValue) || $cmJn2$reactstatelyutils.snapValueToStep(parsedValue, minValue, maxValue, clampStep) > parsedValue || $e18a693eeaf9c060$var$handleDecimalOperation('+', parsedValue, clampStep) <= maxValue)
141
+ , [
142
+ isDisabled,
143
+ isReadOnly,
144
+ minValue,
145
+ maxValue,
146
+ clampStep,
147
+ parsedValue
148
+ ]);
149
+ let canDecrement = $cmJn2$react.useMemo(()=>!isDisabled && !isReadOnly && (isNaN(parsedValue) || isNaN(minValue) || $cmJn2$reactstatelyutils.snapValueToStep(parsedValue, minValue, maxValue, clampStep) < parsedValue || $e18a693eeaf9c060$var$handleDecimalOperation('-', parsedValue, clampStep) >= minValue)
150
+ , [
151
+ isDisabled,
152
+ isReadOnly,
153
+ minValue,
154
+ maxValue,
155
+ clampStep,
156
+ parsedValue
157
+ ]);
158
+ let validate = (value)=>numberParser.isValidPartialNumber(value, minValue, maxValue)
159
+ ;
160
+ return {
161
+ validate: validate,
162
+ increment: increment,
163
+ incrementToMax: incrementToMax,
164
+ decrement: decrement,
165
+ decrementToMin: decrementToMin,
166
+ canIncrement: canIncrement,
167
+ canDecrement: canDecrement,
168
+ minValue: minValue,
169
+ maxValue: maxValue,
170
+ numberValue: parsedValue,
171
+ setInputValue: setInputValue,
172
+ inputValue: inputValue,
173
+ commit: commit
174
+ };
175
+ }
176
+ function $e18a693eeaf9c060$var$handleDecimalOperation(operator, value1, value2) {
177
+ let result = operator === '+' ? value1 + value2 : value1 - value2;
178
+ // Check if we have decimals
179
+ if (value1 % 1 !== 0 || value2 % 1 !== 0) {
180
+ const value1Decimal = value1.toString().split('.');
181
+ const value2Decimal = value2.toString().split('.');
182
+ const value1DecimalLength = value1Decimal[1] && value1Decimal[1].length || 0;
183
+ const value2DecimalLength = value2Decimal[1] && value2Decimal[1].length || 0;
184
+ const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength));
185
+ // Transform the decimals to integers based on the precision
186
+ value1 = Math.round(value1 * multiplier);
187
+ value2 = Math.round(value2 * multiplier);
188
+ // Perform the operation on integers values to make sure we don't get a fancy decimal value
189
+ result = operator === '+' ? value1 + value2 : value1 - value2;
190
+ // Transform the integer result back to decimal
191
+ result /= multiplier;
155
192
  }
156
- };
157
-
158
- let canIncrement = useMemo(() => !isDisabled && !isReadOnly && (isNaN(parsedValue) || isNaN(maxValue) || snapValueToStep(parsedValue, minValue, maxValue, clampStep) > parsedValue || $bb3f0c77930f1734ecd987a3e5d3aa28$var$handleDecimalOperation('+', parsedValue, clampStep) <= maxValue), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);
159
- let canDecrement = useMemo(() => !isDisabled && !isReadOnly && (isNaN(parsedValue) || isNaN(minValue) || snapValueToStep(parsedValue, minValue, maxValue, clampStep) < parsedValue || $bb3f0c77930f1734ecd987a3e5d3aa28$var$handleDecimalOperation('-', parsedValue, clampStep) >= minValue), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);
160
-
161
- let validate = value => numberParser.isValidPartialNumber(value, minValue, maxValue);
162
-
163
- return {
164
- validate,
165
- increment,
166
- incrementToMax,
167
- decrement,
168
- decrementToMin,
169
- canIncrement,
170
- canDecrement,
171
- minValue,
172
- maxValue,
173
- numberValue: parsedValue,
174
- setInputValue,
175
- inputValue,
176
- commit
177
- };
193
+ return result;
178
194
  }
179
195
 
180
- exports.useNumberFieldState = useNumberFieldState;
181
-
182
- function $bb3f0c77930f1734ecd987a3e5d3aa28$var$handleDecimalOperation(operator, value1, value2) {
183
- let result = operator === '+' ? value1 + value2 : value1 - value2; // Check if we have decimals
184
-
185
- if (value1 % 1 !== 0 || value2 % 1 !== 0) {
186
- const value1Decimal = value1.toString().split('.');
187
- const value2Decimal = value2.toString().split('.');
188
- const value1DecimalLength = value1Decimal[1] && value1Decimal[1].length || 0;
189
- const value2DecimalLength = value2Decimal[1] && value2Decimal[1].length || 0;
190
- const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength)); // Transform the decimals to integers based on the precision
191
196
 
192
- value1 = Math.round(value1 * multiplier);
193
- value2 = Math.round(value2 * multiplier); // Perform the operation on integers values to make sure we don't get a fancy decimal value
197
+ $parcel$exportWildcard(module.exports, $e18a693eeaf9c060$exports);
194
198
 
195
- result = operator === '+' ? value1 + value2 : value1 - value2; // Transform the integer result back to decimal
196
199
 
197
- result /= multiplier;
198
- }
199
-
200
- return result;
201
- }
202
200
  //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"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","sources":["./node_modules/@parcel/scope-hoisting/lib/helpers.js","./packages/@react-stately/numberfield/src/useNumberFieldState.ts"],"sourcesContent":["function $parcel$interopDefault(a) {\n return a && a.__esModule ? a.default : a;\n}\n\nfunction $parcel$defineInteropFlag(a) {\n Object.defineProperty(a, '__esModule', {value: true});\n}\n\nfunction $parcel$exportWildcard(dest, source) {\n Object.keys(source).forEach(function(key) {\n if (key === 'default' || key === '__esModule') {\n return;\n }\n\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function get() {\n return source[key];\n },\n });\n });\n\n return dest;\n}\n\nfunction $parcel$missingModule(name) {\n var err = new Error(\"Cannot find module '\" + name + \"'\");\n err.code = 'MODULE_NOT_FOUND';\n throw err;\n}\n\nvar $parcel$global =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof self !== 'undefined'\n ? self\n : typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined'\n ? global\n : {};\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {clamp, snapValueToStep, useControlledState} from '@react-stately/utils';\nimport {NumberFieldProps} from '@react-types/numberfield';\nimport {NumberFormatter, NumberParser} from '@internationalized/number';\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react';\n\nexport interface NumberFieldState {\n /**\n * The current text value of the input. Updated as the user types,\n * and formatted according to `formatOptions` on blur.\n */\n inputValue: string,\n /**\n * The currently parsed number value, or NaN if a valid number could not be parsed.\n * Updated based on the `inputValue` as the user types.\n */\n numberValue: number,\n /** The minimum value of the number field. */\n minValue: number,\n /** The maximum value of the number field. */\n maxValue: number,\n /** Whether the current value can be incremented according to the maximum value and step. */\n canIncrement: boolean,\n /** Whether the current value can be decremented according to the minimum value and step. */\n canDecrement: boolean,\n /**\n * Validates a user input string according to the current locale and format options.\n * Values can be partially entered, and may be valid even if they cannot currently be parsed to a number.\n * Can be used to implement validation as a user types.\n */\n validate(value: string): boolean,\n /** Sets the current text value of the input. */\n setInputValue(val: string): void,\n /**\n * Commits the current input value. The value is parsed to a number, clamped according\n * to the minimum and maximum values of the field, and snapped to the nearest step value.\n * This will fire the `onChange` prop with the new value, and if uncontrolled, update the `numberValue`.\n * Typically this is called when the field is blurred.\n */\n commit(): void,\n /** Increments the current input value to the next step boundary, and fires `onChange`. */\n increment(): void,\n /** Decrements the current input value to the next step boundary, and fires `onChange`. */\n decrement(): void,\n /** Sets the current value to the `maxValue` if any, and fires `onChange`. */\n incrementToMax(): void,\n /** Sets the current value to the `minValue` if any, and fires `onChange`. */\n decrementToMin(): void\n}\n\ninterface NumberFieldStateProps extends NumberFieldProps {\n /**\n * The locale that should be used for parsing.\n * @default 'en-US'\n */\n locale: string\n}\n\n/**\n * Provides state management for a number field component. Number fields allow users to enter a number,\n * and increment or decrement the value using stepper buttons.\n */\nexport function useNumberFieldState(\n props: NumberFieldStateProps\n): NumberFieldState {\n let {\n minValue,\n maxValue,\n step,\n formatOptions,\n value,\n defaultValue,\n onChange,\n locale,\n isDisabled,\n isReadOnly\n } = props;\n\n let [numberValue, setNumberValue] = useControlledState<number>(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);\n let [inputValue, setInputValue] = useState(() => isNaN(numberValue) ? '' : new NumberFormatter(locale, formatOptions).format(numberValue));\n\n let numberParser = useMemo(() => new NumberParser(locale, formatOptions), [locale, formatOptions]);\n let numberingSystem = useMemo(() => numberParser.getNumberingSystem(inputValue), [numberParser, inputValue]);\n let formatter = useMemo(() => new NumberFormatter(locale, {...formatOptions, numberingSystem}), [locale, formatOptions, numberingSystem]);\n let intlOptions = useMemo(() => formatter.resolvedOptions(), [formatter]);\n let format = useCallback((value: number) => isNaN(value) ? '' : formatter.format(value), [formatter]);\n\n let clampStep = !isNaN(step) ? step : 1;\n if (intlOptions.style === 'percent' && isNaN(step)) {\n clampStep = 0.01;\n }\n\n // Update the input value when the number value or format options change. This is done\n // in a useEffect so that the controlled behavior is correct and we only update the\n // textfield after prop changes.\n useEffect(() => {\n setInputValue(format(numberValue));\n }, [numberValue, locale, formatOptions]);\n\n // Store last parsed value in a ref so it can be used by increment/decrement below\n let parsedValue = useMemo(() => numberParser.parse(inputValue), [numberParser, inputValue]);\n let parsed = useRef(0);\n parsed.current = parsedValue;\n\n let commit = () => {\n // Set to empty state if input value is empty\n if (!inputValue.length) {\n setNumberValue(NaN);\n setInputValue(value === undefined ? '' : format(numberValue));\n return;\n }\n\n // if it failed to parse, then reset input to formatted version of current number\n if (isNaN(parsed.current)) {\n setInputValue(format(numberValue));\n return;\n }\n\n // Clamp to min and max, round to the nearest step, and round to specified number of digits\n let clampedValue: number;\n if (isNaN(step)) {\n clampedValue = clamp(parsed.current, minValue, maxValue);\n } else {\n clampedValue = snapValueToStep(parsed.current, minValue, maxValue, step);\n }\n\n clampedValue = numberParser.parse(format(clampedValue));\n setNumberValue(clampedValue);\n\n // in a controlled state, the numberValue won't change, so we won't go back to our old input without help\n setInputValue(format(value === undefined ? clampedValue : numberValue));\n };\n\n let safeNextStep = (operation: '+' | '-', minMax: number) => {\n let prev = parsed.current;\n\n if (isNaN(prev)) {\n // if the input is empty, start from the min/max value when incrementing/decrementing,\n // or zero if there is no min/max value defined.\n let newValue = isNaN(minMax) ? 0 : minMax;\n return snapValueToStep(newValue, minValue, maxValue, clampStep);\n } else {\n // otherwise, first snap the current value to the nearest step. if it moves in the direction\n // we're going, use that value, otherwise add the step and snap that value.\n let newValue = snapValueToStep(prev, minValue, maxValue, clampStep);\n if ((operation === '+' && newValue > prev) || (operation === '-' && newValue < prev)) {\n return newValue;\n }\n\n return snapValueToStep(\n handleDecimalOperation(operation, prev, clampStep),\n minValue,\n maxValue,\n clampStep\n );\n }\n };\n\n let increment = () => {\n setNumberValue((previousValue) => {\n let newValue = safeNextStep('+', minValue);\n\n // if we've arrived at the same value that was previously in the state, the\n // input value should be updated to match\n // ex type 4, press increment, highlight the number in the input, type 4 again, press increment\n // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input\n if (newValue === previousValue) {\n setInputValue(format(newValue));\n }\n\n return newValue;\n });\n };\n\n let decrement = () => {\n setNumberValue((previousValue) => {\n let newValue = safeNextStep('-', maxValue);\n\n if (newValue === previousValue) {\n setInputValue(format(newValue));\n }\n\n return newValue;\n });\n };\n\n let incrementToMax = () => {\n if (maxValue != null) {\n setNumberValue(snapValueToStep(maxValue, minValue, maxValue, clampStep));\n }\n };\n\n let decrementToMin = () => {\n if (minValue != null) {\n setNumberValue(minValue);\n }\n };\n\n let canIncrement = useMemo(() => (\n !isDisabled &&\n !isReadOnly &&\n (\n isNaN(parsedValue) ||\n isNaN(maxValue) ||\n snapValueToStep(parsedValue, minValue, maxValue, clampStep) > parsedValue ||\n handleDecimalOperation('+', parsedValue, clampStep) <= maxValue\n )\n ), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);\n\n let canDecrement = useMemo(() => (\n !isDisabled &&\n !isReadOnly &&\n (\n isNaN(parsedValue) ||\n isNaN(minValue) ||\n snapValueToStep(parsedValue, minValue, maxValue, clampStep) < parsedValue ||\n handleDecimalOperation('-', parsedValue, clampStep) >= minValue\n )\n ), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);\n\n let validate = (value: string) => numberParser.isValidPartialNumber(value, minValue, maxValue);\n\n return {\n validate,\n increment,\n incrementToMax,\n decrement,\n decrementToMin,\n canIncrement,\n canDecrement,\n minValue,\n maxValue,\n numberValue: parsedValue,\n setInputValue,\n inputValue,\n commit\n };\n}\n\nfunction handleDecimalOperation(operator: '-' | '+', value1: number, value2: number): number {\n let result = operator === '+' ? value1 + value2 : value1 - value2;\n\n // Check if we have decimals\n if (value1 % 1 !== 0 || value2 % 1 !== 0) {\n const value1Decimal = value1.toString().split('.');\n const value2Decimal = value2.toString().split('.');\n const value1DecimalLength = (value1Decimal[1] && value1Decimal[1].length) || 0;\n const value2DecimalLength = (value2Decimal[1] && value2Decimal[1].length) || 0;\n const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength));\n\n // Transform the decimals to integers based on the precision\n value1 = Math.round(value1 * multiplier);\n value2 = Math.round(value2 * multiplier);\n\n // Perform the operation on integers values to make sure we don't get a fancy decimal value\n result = operator === '+' ? value1 + value2 : value1 - value2;\n\n // Transform the integer result back to decimal\n result /= multiplier;\n }\n\n return result;\n}\n"],"names":["$parcel$interopDefault","a","__esModule","default","useNumberFieldState","props","minValue","maxValue","step","formatOptions","value","defaultValue","onChange","locale","isDisabled","isReadOnly","numberValue","setNumberValue","useControlledState","isNaN","NaN","inputValue","setInputValue","useState","NumberFormatter","format","numberParser","useMemo","NumberParser","numberingSystem","getNumberingSystem","formatter","intlOptions","resolvedOptions","useCallback","clampStep","style","useEffect","parsedValue","parse","parsed","useRef","current","commit","length","undefined","clampedValue","clamp","snapValueToStep","safeNextStep","operation","minMax","prev","newValue","handleDecimalOperation","increment","previousValue","decrement","incrementToMax","decrementToMin","canIncrement","canDecrement","validate","isValidPartialNumber","operator","value1","value2","result","value1Decimal","toString","split","value2Decimal","value1DecimalLength","value2DecimalLength","multiplier","Math","pow","max","round"],"version":3,"file":"main.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-stately/numberfield/src/index.ts","packages/@react-stately/numberfield/src/useNumberFieldState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n/// <reference types=\"intl-types-extension\" />\n\nexport * from './useNumberFieldState';\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {clamp, snapValueToStep, useControlledState} from '@react-stately/utils';\nimport {NumberFieldProps} from '@react-types/numberfield';\nimport {NumberFormatter, NumberParser} from '@internationalized/number';\nimport {useCallback, useMemo, useRef, useState} from 'react';\n\nexport interface NumberFieldState {\n /**\n * The current text value of the input. Updated as the user types,\n * and formatted according to `formatOptions` on blur.\n */\n inputValue: string,\n /**\n * The currently parsed number value, or NaN if a valid number could not be parsed.\n * Updated based on the `inputValue` as the user types.\n */\n numberValue: number,\n /** The minimum value of the number field. */\n minValue: number,\n /** The maximum value of the number field. */\n maxValue: number,\n /** Whether the current value can be incremented according to the maximum value and step. */\n canIncrement: boolean,\n /** Whether the current value can be decremented according to the minimum value and step. */\n canDecrement: boolean,\n /**\n * Validates a user input string according to the current locale and format options.\n * Values can be partially entered, and may be valid even if they cannot currently be parsed to a number.\n * Can be used to implement validation as a user types.\n */\n validate(value: string): boolean,\n /** Sets the current text value of the input. */\n setInputValue(val: string): void,\n /**\n * Commits the current input value. The value is parsed to a number, clamped according\n * to the minimum and maximum values of the field, and snapped to the nearest step value.\n * This will fire the `onChange` prop with the new value, and if uncontrolled, update the `numberValue`.\n * Typically this is called when the field is blurred.\n */\n commit(): void,\n /** Increments the current input value to the next step boundary, and fires `onChange`. */\n increment(): void,\n /** Decrements the current input value to the next step boundary, and fires `onChange`. */\n decrement(): void,\n /** Sets the current value to the `maxValue` if any, and fires `onChange`. */\n incrementToMax(): void,\n /** Sets the current value to the `minValue` if any, and fires `onChange`. */\n decrementToMin(): void\n}\n\ninterface NumberFieldStateProps extends NumberFieldProps {\n /**\n * The locale that should be used for parsing.\n * @default 'en-US'\n */\n locale: string\n}\n\n/**\n * Provides state management for a number field component. Number fields allow users to enter a number,\n * and increment or decrement the value using stepper buttons.\n */\nexport function useNumberFieldState(\n props: NumberFieldStateProps\n): NumberFieldState {\n let {\n minValue,\n maxValue,\n step,\n formatOptions,\n value,\n defaultValue,\n onChange,\n locale,\n isDisabled,\n isReadOnly\n } = props;\n\n let [numberValue, setNumberValue] = useControlledState<number>(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);\n let [inputValue, setInputValue] = useState(() => isNaN(numberValue) ? '' : new NumberFormatter(locale, formatOptions).format(numberValue));\n\n let numberParser = useMemo(() => new NumberParser(locale, formatOptions), [locale, formatOptions]);\n let numberingSystem = useMemo(() => numberParser.getNumberingSystem(inputValue), [numberParser, inputValue]);\n let formatter = useMemo(() => new NumberFormatter(locale, {...formatOptions, numberingSystem}), [locale, formatOptions, numberingSystem]);\n let intlOptions = useMemo(() => formatter.resolvedOptions(), [formatter]);\n let format = useCallback((value: number) => isNaN(value) ? '' : formatter.format(value), [formatter]);\n\n let clampStep = !isNaN(step) ? step : 1;\n if (intlOptions.style === 'percent' && isNaN(step)) {\n clampStep = 0.01;\n }\n\n // Update the input value when the number value or format options change. This is done\n // in a useEffect so that the controlled behavior is correct and we only update the\n // textfield after prop changes.\n let prevValue = useRef(numberValue);\n let prevLocale = useRef(locale);\n let prevFormatOptions = useRef(formatOptions);\n if (!Object.is(numberValue, prevValue.current) || locale !== prevLocale.current || formatOptions !== prevFormatOptions.current) {\n setInputValue(format(numberValue));\n prevValue.current = numberValue;\n prevLocale.current = locale;\n prevFormatOptions.current = formatOptions;\n }\n\n // Store last parsed value in a ref so it can be used by increment/decrement below\n let parsedValue = useMemo(() => numberParser.parse(inputValue), [numberParser, inputValue]);\n let parsed = useRef(0);\n parsed.current = parsedValue;\n\n let commit = () => {\n // Set to empty state if input value is empty\n if (!inputValue.length) {\n setNumberValue(NaN);\n setInputValue(value === undefined ? '' : format(numberValue));\n return;\n }\n\n // if it failed to parse, then reset input to formatted version of current number\n if (isNaN(parsed.current)) {\n setInputValue(format(numberValue));\n return;\n }\n\n // Clamp to min and max, round to the nearest step, and round to specified number of digits\n let clampedValue: number;\n if (isNaN(step)) {\n clampedValue = clamp(parsed.current, minValue, maxValue);\n } else {\n clampedValue = snapValueToStep(parsed.current, minValue, maxValue, step);\n }\n\n clampedValue = numberParser.parse(format(clampedValue));\n setNumberValue(clampedValue);\n\n // in a controlled state, the numberValue won't change, so we won't go back to our old input without help\n setInputValue(format(value === undefined ? clampedValue : numberValue));\n };\n\n let safeNextStep = (operation: '+' | '-', minMax: number) => {\n let prev = parsed.current;\n\n if (isNaN(prev)) {\n // if the input is empty, start from the min/max value when incrementing/decrementing,\n // or zero if there is no min/max value defined.\n let newValue = isNaN(minMax) ? 0 : minMax;\n return snapValueToStep(newValue, minValue, maxValue, clampStep);\n } else {\n // otherwise, first snap the current value to the nearest step. if it moves in the direction\n // we're going, use that value, otherwise add the step and snap that value.\n let newValue = snapValueToStep(prev, minValue, maxValue, clampStep);\n if ((operation === '+' && newValue > prev) || (operation === '-' && newValue < prev)) {\n return newValue;\n }\n\n return snapValueToStep(\n handleDecimalOperation(operation, prev, clampStep),\n minValue,\n maxValue,\n clampStep\n );\n }\n };\n\n let increment = () => {\n let newValue = safeNextStep('+', minValue);\n\n // if we've arrived at the same value that was previously in the state, the\n // input value should be updated to match\n // ex type 4, press increment, highlight the number in the input, type 4 again, press increment\n // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input\n if (newValue === numberValue) {\n setInputValue(format(newValue));\n }\n\n setNumberValue(newValue);\n };\n\n let decrement = () => {\n let newValue = safeNextStep('-', maxValue);\n\n if (newValue === numberValue) {\n setInputValue(format(newValue));\n }\n\n setNumberValue(newValue);\n };\n\n let incrementToMax = () => {\n if (maxValue != null) {\n setNumberValue(snapValueToStep(maxValue, minValue, maxValue, clampStep));\n }\n };\n\n let decrementToMin = () => {\n if (minValue != null) {\n setNumberValue(minValue);\n }\n };\n\n let canIncrement = useMemo(() => (\n !isDisabled &&\n !isReadOnly &&\n (\n isNaN(parsedValue) ||\n isNaN(maxValue) ||\n snapValueToStep(parsedValue, minValue, maxValue, clampStep) > parsedValue ||\n handleDecimalOperation('+', parsedValue, clampStep) <= maxValue\n )\n ), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);\n\n let canDecrement = useMemo(() => (\n !isDisabled &&\n !isReadOnly &&\n (\n isNaN(parsedValue) ||\n isNaN(minValue) ||\n snapValueToStep(parsedValue, minValue, maxValue, clampStep) < parsedValue ||\n handleDecimalOperation('-', parsedValue, clampStep) >= minValue\n )\n ), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);\n\n let validate = (value: string) => numberParser.isValidPartialNumber(value, minValue, maxValue);\n\n return {\n validate,\n increment,\n incrementToMax,\n decrement,\n decrementToMin,\n canIncrement,\n canDecrement,\n minValue,\n maxValue,\n numberValue: parsedValue,\n setInputValue,\n inputValue,\n commit\n };\n}\n\nfunction handleDecimalOperation(operator: '-' | '+', value1: number, value2: number): number {\n let result = operator === '+' ? value1 + value2 : value1 - value2;\n\n // Check if we have decimals\n if (value1 % 1 !== 0 || value2 % 1 !== 0) {\n const value1Decimal = value1.toString().split('.');\n const value2Decimal = value2.toString().split('.');\n const value1DecimalLength = (value1Decimal[1] && value1Decimal[1].length) || 0;\n const value2DecimalLength = (value2Decimal[1] && value2Decimal[1].length) || 0;\n const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength));\n\n // Transform the decimals to integers based on the precision\n value1 = Math.round(value1 * multiplier);\n value2 = Math.round(value2 * multiplier);\n\n // Perform the operation on integers values to make sure we don't get a fancy decimal value\n result = operator === '+' ? value1 + value2 : value1 - value2;\n\n // Transform the integer result back to decimal\n result /= multiplier;\n }\n\n return result;\n}\n"],"names":[],"version":3,"file":"main.js.map"}
package/dist/module.js CHANGED
@@ -1,180 +1,184 @@
1
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
- import { NumberFormatter, NumberParser } from "@internationalized/number";
3
- import { clamp, snapValueToStep, useControlledState } from "@react-stately/utils";
4
- import _babelRuntimeHelpersEsmExtends from "@babel/runtime/helpers/esm/extends";
1
+ import {useControlledState as $vhjCi$useControlledState, clamp as $vhjCi$clamp, snapValueToStep as $vhjCi$snapValueToStep} from "@react-stately/utils";
2
+ import {NumberFormatter as $vhjCi$NumberFormatter, NumberParser as $vhjCi$NumberParser} from "@internationalized/number";
3
+ import {useState as $vhjCi$useState, useMemo as $vhjCi$useMemo, useCallback as $vhjCi$useCallback, useRef as $vhjCi$useRef} from "react";
5
4
 
6
- /**
7
- * Provides state management for a number field component. Number fields allow users to enter a number,
8
- * and increment or decrement the value using stepper buttons.
9
- */
10
- export function useNumberFieldState(props) {
11
- let {
12
- minValue,
13
- maxValue,
14
- step,
15
- formatOptions,
16
- value,
17
- defaultValue,
18
- onChange,
19
- locale,
20
- isDisabled,
21
- isReadOnly
22
- } = props;
23
- let [numberValue, setNumberValue] = useControlledState(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);
24
- let [inputValue, setInputValue] = useState(() => isNaN(numberValue) ? '' : new NumberFormatter(locale, formatOptions).format(numberValue));
25
- let numberParser = useMemo(() => new NumberParser(locale, formatOptions), [locale, formatOptions]);
26
- let numberingSystem = useMemo(() => numberParser.getNumberingSystem(inputValue), [numberParser, inputValue]);
27
- let formatter = useMemo(() => new NumberFormatter(locale, _babelRuntimeHelpersEsmExtends({}, formatOptions, {
28
- numberingSystem
29
- })), [locale, formatOptions, numberingSystem]);
30
- let intlOptions = useMemo(() => formatter.resolvedOptions(), [formatter]);
31
- let format = useCallback(value => isNaN(value) ? '' : formatter.format(value), [formatter]);
32
- let clampStep = !isNaN(step) ? step : 1;
33
-
34
- if (intlOptions.style === 'percent' && isNaN(step)) {
35
- clampStep = 0.01;
36
- } // Update the input value when the number value or format options change. This is done
37
- // in a useEffect so that the controlled behavior is correct and we only update the
38
- // textfield after prop changes.
39
-
40
-
41
- useEffect(() => {
42
- setInputValue(format(numberValue));
43
- }, [numberValue, locale, formatOptions]); // Store last parsed value in a ref so it can be used by increment/decrement below
44
-
45
- let parsedValue = useMemo(() => numberParser.parse(inputValue), [numberParser, inputValue]);
46
- let parsed = useRef(0);
47
- parsed.current = parsedValue;
48
-
49
- let commit = () => {
50
- // Set to empty state if input value is empty
51
- if (!inputValue.length) {
52
- setNumberValue(NaN);
53
- setInputValue(value === undefined ? '' : format(numberValue));
54
- return;
55
- } // if it failed to parse, then reset input to formatted version of current number
56
-
57
-
58
- if (isNaN(parsed.current)) {
59
- setInputValue(format(numberValue));
60
- return;
61
- } // Clamp to min and max, round to the nearest step, and round to specified number of digits
62
-
63
-
64
- let clampedValue;
65
-
66
- if (isNaN(step)) {
67
- clampedValue = clamp(parsed.current, minValue, maxValue);
68
- } else {
69
- clampedValue = snapValueToStep(parsed.current, minValue, maxValue, step);
70
- }
71
-
72
- clampedValue = numberParser.parse(format(clampedValue));
73
- setNumberValue(clampedValue); // in a controlled state, the numberValue won't change, so we won't go back to our old input without help
74
-
75
- setInputValue(format(value === undefined ? clampedValue : numberValue));
76
- };
77
-
78
- let safeNextStep = (operation, minMax) => {
79
- let prev = parsed.current;
80
-
81
- if (isNaN(prev)) {
82
- // if the input is empty, start from the min/max value when incrementing/decrementing,
83
- // or zero if there is no min/max value defined.
84
- let newValue = isNaN(minMax) ? 0 : minMax;
85
- return snapValueToStep(newValue, minValue, maxValue, clampStep);
86
- } else {
87
- // otherwise, first snap the current value to the nearest step. if it moves in the direction
88
- // we're going, use that value, otherwise add the step and snap that value.
89
- let newValue = snapValueToStep(prev, minValue, maxValue, clampStep);
90
-
91
- if (operation === '+' && newValue > prev || operation === '-' && newValue < prev) {
92
- return newValue;
93
- }
94
-
95
- return snapValueToStep($b6f3c0268c2239b947a18381443e4550$var$handleDecimalOperation(operation, prev, clampStep), minValue, maxValue, clampStep);
96
- }
97
- };
98
-
99
- let increment = () => {
100
- setNumberValue(previousValue => {
101
- let newValue = safeNextStep('+', minValue); // if we've arrived at the same value that was previously in the state, the
102
- // input value should be updated to match
103
- // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
104
- // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
105
-
106
- if (newValue === previousValue) {
107
- setInputValue(format(newValue));
108
- }
109
-
110
- return newValue;
111
- });
112
- };
113
-
114
- let decrement = () => {
115
- setNumberValue(previousValue => {
116
- let newValue = safeNextStep('-', maxValue);
117
-
118
- if (newValue === previousValue) {
119
- setInputValue(format(newValue));
120
- }
121
-
122
- return newValue;
123
- });
124
- };
125
-
126
- let incrementToMax = () => {
127
- if (maxValue != null) {
128
- setNumberValue(snapValueToStep(maxValue, minValue, maxValue, clampStep));
5
+ function $parcel$export(e, n, v, s) {
6
+ Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
7
+ }
8
+ var $de67e98908f0c6ee$exports = {};
9
+
10
+ $parcel$export($de67e98908f0c6ee$exports, "useNumberFieldState", () => $de67e98908f0c6ee$export$7f629e9dc1ecf37c);
11
+
12
+
13
+
14
+ function $de67e98908f0c6ee$export$7f629e9dc1ecf37c(props) {
15
+ let { minValue: minValue , maxValue: maxValue , step: step , formatOptions: formatOptions , value: value1 , defaultValue: defaultValue , onChange: onChange , locale: locale , isDisabled: isDisabled , isReadOnly: isReadOnly } = props;
16
+ let [numberValue, setNumberValue] = $vhjCi$useControlledState(value1, isNaN(defaultValue) ? NaN : defaultValue, onChange);
17
+ let [inputValue, setInputValue] = $vhjCi$useState(()=>isNaN(numberValue) ? '' : new $vhjCi$NumberFormatter(locale, formatOptions).format(numberValue)
18
+ );
19
+ let numberParser = $vhjCi$useMemo(()=>new $vhjCi$NumberParser(locale, formatOptions)
20
+ , [
21
+ locale,
22
+ formatOptions
23
+ ]);
24
+ let numberingSystem = $vhjCi$useMemo(()=>numberParser.getNumberingSystem(inputValue)
25
+ , [
26
+ numberParser,
27
+ inputValue
28
+ ]);
29
+ let formatter = $vhjCi$useMemo(()=>new $vhjCi$NumberFormatter(locale, {
30
+ ...formatOptions,
31
+ numberingSystem: numberingSystem
32
+ })
33
+ , [
34
+ locale,
35
+ formatOptions,
36
+ numberingSystem
37
+ ]);
38
+ let intlOptions = $vhjCi$useMemo(()=>formatter.resolvedOptions()
39
+ , [
40
+ formatter
41
+ ]);
42
+ let format = $vhjCi$useCallback((value)=>isNaN(value) ? '' : formatter.format(value)
43
+ , [
44
+ formatter
45
+ ]);
46
+ let clampStep = !isNaN(step) ? step : 1;
47
+ if (intlOptions.style === 'percent' && isNaN(step)) clampStep = 0.01;
48
+ // Update the input value when the number value or format options change. This is done
49
+ // in a useEffect so that the controlled behavior is correct and we only update the
50
+ // textfield after prop changes.
51
+ let prevValue = $vhjCi$useRef(numberValue);
52
+ let prevLocale = $vhjCi$useRef(locale);
53
+ let prevFormatOptions = $vhjCi$useRef(formatOptions);
54
+ if (!Object.is(numberValue, prevValue.current) || locale !== prevLocale.current || formatOptions !== prevFormatOptions.current) {
55
+ setInputValue(format(numberValue));
56
+ prevValue.current = numberValue;
57
+ prevLocale.current = locale;
58
+ prevFormatOptions.current = formatOptions;
129
59
  }
130
- };
131
-
132
- let decrementToMin = () => {
133
- if (minValue != null) {
134
- setNumberValue(minValue);
60
+ // Store last parsed value in a ref so it can be used by increment/decrement below
61
+ let parsedValue = $vhjCi$useMemo(()=>numberParser.parse(inputValue)
62
+ , [
63
+ numberParser,
64
+ inputValue
65
+ ]);
66
+ let parsed = $vhjCi$useRef(0);
67
+ parsed.current = parsedValue;
68
+ let commit = ()=>{
69
+ // Set to empty state if input value is empty
70
+ if (!inputValue.length) {
71
+ setNumberValue(NaN);
72
+ setInputValue(value1 === undefined ? '' : format(numberValue));
73
+ return;
74
+ }
75
+ // if it failed to parse, then reset input to formatted version of current number
76
+ if (isNaN(parsed.current)) {
77
+ setInputValue(format(numberValue));
78
+ return;
79
+ }
80
+ // Clamp to min and max, round to the nearest step, and round to specified number of digits
81
+ let clampedValue;
82
+ if (isNaN(step)) clampedValue = $vhjCi$clamp(parsed.current, minValue, maxValue);
83
+ else clampedValue = $vhjCi$snapValueToStep(parsed.current, minValue, maxValue, step);
84
+ clampedValue = numberParser.parse(format(clampedValue));
85
+ setNumberValue(clampedValue);
86
+ // in a controlled state, the numberValue won't change, so we won't go back to our old input without help
87
+ setInputValue(format(value1 === undefined ? clampedValue : numberValue));
88
+ };
89
+ let safeNextStep = (operation, minMax)=>{
90
+ let prev = parsed.current;
91
+ if (isNaN(prev)) {
92
+ // if the input is empty, start from the min/max value when incrementing/decrementing,
93
+ // or zero if there is no min/max value defined.
94
+ let newValue = isNaN(minMax) ? 0 : minMax;
95
+ return $vhjCi$snapValueToStep(newValue, minValue, maxValue, clampStep);
96
+ } else {
97
+ // otherwise, first snap the current value to the nearest step. if it moves in the direction
98
+ // we're going, use that value, otherwise add the step and snap that value.
99
+ let newValue = $vhjCi$snapValueToStep(prev, minValue, maxValue, clampStep);
100
+ if (operation === '+' && newValue > prev || operation === '-' && newValue < prev) return newValue;
101
+ return $vhjCi$snapValueToStep($de67e98908f0c6ee$var$handleDecimalOperation(operation, prev, clampStep), minValue, maxValue, clampStep);
102
+ }
103
+ };
104
+ let increment = ()=>{
105
+ let newValue = safeNextStep('+', minValue);
106
+ // if we've arrived at the same value that was previously in the state, the
107
+ // input value should be updated to match
108
+ // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
109
+ // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
110
+ if (newValue === numberValue) setInputValue(format(newValue));
111
+ setNumberValue(newValue);
112
+ };
113
+ let decrement = ()=>{
114
+ let newValue = safeNextStep('-', maxValue);
115
+ if (newValue === numberValue) setInputValue(format(newValue));
116
+ setNumberValue(newValue);
117
+ };
118
+ let incrementToMax = ()=>{
119
+ if (maxValue != null) setNumberValue($vhjCi$snapValueToStep(maxValue, minValue, maxValue, clampStep));
120
+ };
121
+ let decrementToMin = ()=>{
122
+ if (minValue != null) setNumberValue(minValue);
123
+ };
124
+ let canIncrement = $vhjCi$useMemo(()=>!isDisabled && !isReadOnly && (isNaN(parsedValue) || isNaN(maxValue) || $vhjCi$snapValueToStep(parsedValue, minValue, maxValue, clampStep) > parsedValue || $de67e98908f0c6ee$var$handleDecimalOperation('+', parsedValue, clampStep) <= maxValue)
125
+ , [
126
+ isDisabled,
127
+ isReadOnly,
128
+ minValue,
129
+ maxValue,
130
+ clampStep,
131
+ parsedValue
132
+ ]);
133
+ let canDecrement = $vhjCi$useMemo(()=>!isDisabled && !isReadOnly && (isNaN(parsedValue) || isNaN(minValue) || $vhjCi$snapValueToStep(parsedValue, minValue, maxValue, clampStep) < parsedValue || $de67e98908f0c6ee$var$handleDecimalOperation('-', parsedValue, clampStep) >= minValue)
134
+ , [
135
+ isDisabled,
136
+ isReadOnly,
137
+ minValue,
138
+ maxValue,
139
+ clampStep,
140
+ parsedValue
141
+ ]);
142
+ let validate = (value)=>numberParser.isValidPartialNumber(value, minValue, maxValue)
143
+ ;
144
+ return {
145
+ validate: validate,
146
+ increment: increment,
147
+ incrementToMax: incrementToMax,
148
+ decrement: decrement,
149
+ decrementToMin: decrementToMin,
150
+ canIncrement: canIncrement,
151
+ canDecrement: canDecrement,
152
+ minValue: minValue,
153
+ maxValue: maxValue,
154
+ numberValue: parsedValue,
155
+ setInputValue: setInputValue,
156
+ inputValue: inputValue,
157
+ commit: commit
158
+ };
159
+ }
160
+ function $de67e98908f0c6ee$var$handleDecimalOperation(operator, value1, value2) {
161
+ let result = operator === '+' ? value1 + value2 : value1 - value2;
162
+ // Check if we have decimals
163
+ if (value1 % 1 !== 0 || value2 % 1 !== 0) {
164
+ const value1Decimal = value1.toString().split('.');
165
+ const value2Decimal = value2.toString().split('.');
166
+ const value1DecimalLength = value1Decimal[1] && value1Decimal[1].length || 0;
167
+ const value2DecimalLength = value2Decimal[1] && value2Decimal[1].length || 0;
168
+ const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength));
169
+ // Transform the decimals to integers based on the precision
170
+ value1 = Math.round(value1 * multiplier);
171
+ value2 = Math.round(value2 * multiplier);
172
+ // Perform the operation on integers values to make sure we don't get a fancy decimal value
173
+ result = operator === '+' ? value1 + value2 : value1 - value2;
174
+ // Transform the integer result back to decimal
175
+ result /= multiplier;
135
176
  }
136
- };
137
-
138
- let canIncrement = useMemo(() => !isDisabled && !isReadOnly && (isNaN(parsedValue) || isNaN(maxValue) || snapValueToStep(parsedValue, minValue, maxValue, clampStep) > parsedValue || $b6f3c0268c2239b947a18381443e4550$var$handleDecimalOperation('+', parsedValue, clampStep) <= maxValue), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);
139
- let canDecrement = useMemo(() => !isDisabled && !isReadOnly && (isNaN(parsedValue) || isNaN(minValue) || snapValueToStep(parsedValue, minValue, maxValue, clampStep) < parsedValue || $b6f3c0268c2239b947a18381443e4550$var$handleDecimalOperation('-', parsedValue, clampStep) >= minValue), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);
140
-
141
- let validate = value => numberParser.isValidPartialNumber(value, minValue, maxValue);
142
-
143
- return {
144
- validate,
145
- increment,
146
- incrementToMax,
147
- decrement,
148
- decrementToMin,
149
- canIncrement,
150
- canDecrement,
151
- minValue,
152
- maxValue,
153
- numberValue: parsedValue,
154
- setInputValue,
155
- inputValue,
156
- commit
157
- };
177
+ return result;
158
178
  }
159
179
 
160
- function $b6f3c0268c2239b947a18381443e4550$var$handleDecimalOperation(operator, value1, value2) {
161
- let result = operator === '+' ? value1 + value2 : value1 - value2; // Check if we have decimals
162
-
163
- if (value1 % 1 !== 0 || value2 % 1 !== 0) {
164
- const value1Decimal = value1.toString().split('.');
165
- const value2Decimal = value2.toString().split('.');
166
- const value1DecimalLength = value1Decimal[1] && value1Decimal[1].length || 0;
167
- const value2DecimalLength = value2Decimal[1] && value2Decimal[1].length || 0;
168
- const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength)); // Transform the decimals to integers based on the precision
169
180
 
170
- value1 = Math.round(value1 * multiplier);
171
- value2 = Math.round(value2 * multiplier); // Perform the operation on integers values to make sure we don't get a fancy decimal value
172
181
 
173
- result = operator === '+' ? value1 + value2 : value1 - value2; // Transform the integer result back to decimal
174
182
 
175
- result /= multiplier;
176
- }
177
-
178
- return result;
179
- }
183
+ export {$de67e98908f0c6ee$export$7f629e9dc1ecf37c as useNumberFieldState};
180
184
  //# sourceMappingURL=module.js.map
@@ -1 +1 @@
1
- {"mappings":"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","sources":["./packages/@react-stately/numberfield/src/useNumberFieldState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {clamp, snapValueToStep, useControlledState} from '@react-stately/utils';\nimport {NumberFieldProps} from '@react-types/numberfield';\nimport {NumberFormatter, NumberParser} from '@internationalized/number';\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react';\n\nexport interface NumberFieldState {\n /**\n * The current text value of the input. Updated as the user types,\n * and formatted according to `formatOptions` on blur.\n */\n inputValue: string,\n /**\n * The currently parsed number value, or NaN if a valid number could not be parsed.\n * Updated based on the `inputValue` as the user types.\n */\n numberValue: number,\n /** The minimum value of the number field. */\n minValue: number,\n /** The maximum value of the number field. */\n maxValue: number,\n /** Whether the current value can be incremented according to the maximum value and step. */\n canIncrement: boolean,\n /** Whether the current value can be decremented according to the minimum value and step. */\n canDecrement: boolean,\n /**\n * Validates a user input string according to the current locale and format options.\n * Values can be partially entered, and may be valid even if they cannot currently be parsed to a number.\n * Can be used to implement validation as a user types.\n */\n validate(value: string): boolean,\n /** Sets the current text value of the input. */\n setInputValue(val: string): void,\n /**\n * Commits the current input value. The value is parsed to a number, clamped according\n * to the minimum and maximum values of the field, and snapped to the nearest step value.\n * This will fire the `onChange` prop with the new value, and if uncontrolled, update the `numberValue`.\n * Typically this is called when the field is blurred.\n */\n commit(): void,\n /** Increments the current input value to the next step boundary, and fires `onChange`. */\n increment(): void,\n /** Decrements the current input value to the next step boundary, and fires `onChange`. */\n decrement(): void,\n /** Sets the current value to the `maxValue` if any, and fires `onChange`. */\n incrementToMax(): void,\n /** Sets the current value to the `minValue` if any, and fires `onChange`. */\n decrementToMin(): void\n}\n\ninterface NumberFieldStateProps extends NumberFieldProps {\n /**\n * The locale that should be used for parsing.\n * @default 'en-US'\n */\n locale: string\n}\n\n/**\n * Provides state management for a number field component. Number fields allow users to enter a number,\n * and increment or decrement the value using stepper buttons.\n */\nexport function useNumberFieldState(\n props: NumberFieldStateProps\n): NumberFieldState {\n let {\n minValue,\n maxValue,\n step,\n formatOptions,\n value,\n defaultValue,\n onChange,\n locale,\n isDisabled,\n isReadOnly\n } = props;\n\n let [numberValue, setNumberValue] = useControlledState<number>(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);\n let [inputValue, setInputValue] = useState(() => isNaN(numberValue) ? '' : new NumberFormatter(locale, formatOptions).format(numberValue));\n\n let numberParser = useMemo(() => new NumberParser(locale, formatOptions), [locale, formatOptions]);\n let numberingSystem = useMemo(() => numberParser.getNumberingSystem(inputValue), [numberParser, inputValue]);\n let formatter = useMemo(() => new NumberFormatter(locale, {...formatOptions, numberingSystem}), [locale, formatOptions, numberingSystem]);\n let intlOptions = useMemo(() => formatter.resolvedOptions(), [formatter]);\n let format = useCallback((value: number) => isNaN(value) ? '' : formatter.format(value), [formatter]);\n\n let clampStep = !isNaN(step) ? step : 1;\n if (intlOptions.style === 'percent' && isNaN(step)) {\n clampStep = 0.01;\n }\n\n // Update the input value when the number value or format options change. This is done\n // in a useEffect so that the controlled behavior is correct and we only update the\n // textfield after prop changes.\n useEffect(() => {\n setInputValue(format(numberValue));\n }, [numberValue, locale, formatOptions]);\n\n // Store last parsed value in a ref so it can be used by increment/decrement below\n let parsedValue = useMemo(() => numberParser.parse(inputValue), [numberParser, inputValue]);\n let parsed = useRef(0);\n parsed.current = parsedValue;\n\n let commit = () => {\n // Set to empty state if input value is empty\n if (!inputValue.length) {\n setNumberValue(NaN);\n setInputValue(value === undefined ? '' : format(numberValue));\n return;\n }\n\n // if it failed to parse, then reset input to formatted version of current number\n if (isNaN(parsed.current)) {\n setInputValue(format(numberValue));\n return;\n }\n\n // Clamp to min and max, round to the nearest step, and round to specified number of digits\n let clampedValue: number;\n if (isNaN(step)) {\n clampedValue = clamp(parsed.current, minValue, maxValue);\n } else {\n clampedValue = snapValueToStep(parsed.current, minValue, maxValue, step);\n }\n\n clampedValue = numberParser.parse(format(clampedValue));\n setNumberValue(clampedValue);\n\n // in a controlled state, the numberValue won't change, so we won't go back to our old input without help\n setInputValue(format(value === undefined ? clampedValue : numberValue));\n };\n\n let safeNextStep = (operation: '+' | '-', minMax: number) => {\n let prev = parsed.current;\n\n if (isNaN(prev)) {\n // if the input is empty, start from the min/max value when incrementing/decrementing,\n // or zero if there is no min/max value defined.\n let newValue = isNaN(minMax) ? 0 : minMax;\n return snapValueToStep(newValue, minValue, maxValue, clampStep);\n } else {\n // otherwise, first snap the current value to the nearest step. if it moves in the direction\n // we're going, use that value, otherwise add the step and snap that value.\n let newValue = snapValueToStep(prev, minValue, maxValue, clampStep);\n if ((operation === '+' && newValue > prev) || (operation === '-' && newValue < prev)) {\n return newValue;\n }\n\n return snapValueToStep(\n handleDecimalOperation(operation, prev, clampStep),\n minValue,\n maxValue,\n clampStep\n );\n }\n };\n\n let increment = () => {\n setNumberValue((previousValue) => {\n let newValue = safeNextStep('+', minValue);\n\n // if we've arrived at the same value that was previously in the state, the\n // input value should be updated to match\n // ex type 4, press increment, highlight the number in the input, type 4 again, press increment\n // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input\n if (newValue === previousValue) {\n setInputValue(format(newValue));\n }\n\n return newValue;\n });\n };\n\n let decrement = () => {\n setNumberValue((previousValue) => {\n let newValue = safeNextStep('-', maxValue);\n\n if (newValue === previousValue) {\n setInputValue(format(newValue));\n }\n\n return newValue;\n });\n };\n\n let incrementToMax = () => {\n if (maxValue != null) {\n setNumberValue(snapValueToStep(maxValue, minValue, maxValue, clampStep));\n }\n };\n\n let decrementToMin = () => {\n if (minValue != null) {\n setNumberValue(minValue);\n }\n };\n\n let canIncrement = useMemo(() => (\n !isDisabled &&\n !isReadOnly &&\n (\n isNaN(parsedValue) ||\n isNaN(maxValue) ||\n snapValueToStep(parsedValue, minValue, maxValue, clampStep) > parsedValue ||\n handleDecimalOperation('+', parsedValue, clampStep) <= maxValue\n )\n ), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);\n\n let canDecrement = useMemo(() => (\n !isDisabled &&\n !isReadOnly &&\n (\n isNaN(parsedValue) ||\n isNaN(minValue) ||\n snapValueToStep(parsedValue, minValue, maxValue, clampStep) < parsedValue ||\n handleDecimalOperation('-', parsedValue, clampStep) >= minValue\n )\n ), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);\n\n let validate = (value: string) => numberParser.isValidPartialNumber(value, minValue, maxValue);\n\n return {\n validate,\n increment,\n incrementToMax,\n decrement,\n decrementToMin,\n canIncrement,\n canDecrement,\n minValue,\n maxValue,\n numberValue: parsedValue,\n setInputValue,\n inputValue,\n commit\n };\n}\n\nfunction handleDecimalOperation(operator: '-' | '+', value1: number, value2: number): number {\n let result = operator === '+' ? value1 + value2 : value1 - value2;\n\n // Check if we have decimals\n if (value1 % 1 !== 0 || value2 % 1 !== 0) {\n const value1Decimal = value1.toString().split('.');\n const value2Decimal = value2.toString().split('.');\n const value1DecimalLength = (value1Decimal[1] && value1Decimal[1].length) || 0;\n const value2DecimalLength = (value2Decimal[1] && value2Decimal[1].length) || 0;\n const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength));\n\n // Transform the decimals to integers based on the precision\n value1 = Math.round(value1 * multiplier);\n value2 = Math.round(value2 * multiplier);\n\n // Perform the operation on integers values to make sure we don't get a fancy decimal value\n result = operator === '+' ? value1 + value2 : value1 - value2;\n\n // Transform the integer result back to decimal\n result /= multiplier;\n }\n\n return result;\n}\n"],"names":["useNumberFieldState","props","minValue","maxValue","step","formatOptions","value","defaultValue","onChange","locale","isDisabled","isReadOnly","numberValue","setNumberValue","useControlledState","isNaN","NaN","inputValue","setInputValue","useState","NumberFormatter","format","numberParser","useMemo","NumberParser","numberingSystem","getNumberingSystem","formatter","intlOptions","resolvedOptions","useCallback","clampStep","style","useEffect","parsedValue","parse","parsed","useRef","current","commit","length","undefined","clampedValue","clamp","snapValueToStep","safeNextStep","operation","minMax","prev","newValue","handleDecimalOperation","increment","previousValue","decrement","incrementToMax","decrementToMin","canIncrement","canDecrement","validate","isValidPartialNumber","operator","value1","value2","result","value1Decimal","toString","split","value2Decimal","value1DecimalLength","value2DecimalLength","multiplier","Math","pow","max","round"],"version":3,"file":"module.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-stately/numberfield/src/index.ts","packages/@react-stately/numberfield/src/useNumberFieldState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n/// <reference types=\"intl-types-extension\" />\n\nexport * from './useNumberFieldState';\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {clamp, snapValueToStep, useControlledState} from '@react-stately/utils';\nimport {NumberFieldProps} from '@react-types/numberfield';\nimport {NumberFormatter, NumberParser} from '@internationalized/number';\nimport {useCallback, useMemo, useRef, useState} from 'react';\n\nexport interface NumberFieldState {\n /**\n * The current text value of the input. Updated as the user types,\n * and formatted according to `formatOptions` on blur.\n */\n inputValue: string,\n /**\n * The currently parsed number value, or NaN if a valid number could not be parsed.\n * Updated based on the `inputValue` as the user types.\n */\n numberValue: number,\n /** The minimum value of the number field. */\n minValue: number,\n /** The maximum value of the number field. */\n maxValue: number,\n /** Whether the current value can be incremented according to the maximum value and step. */\n canIncrement: boolean,\n /** Whether the current value can be decremented according to the minimum value and step. */\n canDecrement: boolean,\n /**\n * Validates a user input string according to the current locale and format options.\n * Values can be partially entered, and may be valid even if they cannot currently be parsed to a number.\n * Can be used to implement validation as a user types.\n */\n validate(value: string): boolean,\n /** Sets the current text value of the input. */\n setInputValue(val: string): void,\n /**\n * Commits the current input value. The value is parsed to a number, clamped according\n * to the minimum and maximum values of the field, and snapped to the nearest step value.\n * This will fire the `onChange` prop with the new value, and if uncontrolled, update the `numberValue`.\n * Typically this is called when the field is blurred.\n */\n commit(): void,\n /** Increments the current input value to the next step boundary, and fires `onChange`. */\n increment(): void,\n /** Decrements the current input value to the next step boundary, and fires `onChange`. */\n decrement(): void,\n /** Sets the current value to the `maxValue` if any, and fires `onChange`. */\n incrementToMax(): void,\n /** Sets the current value to the `minValue` if any, and fires `onChange`. */\n decrementToMin(): void\n}\n\ninterface NumberFieldStateProps extends NumberFieldProps {\n /**\n * The locale that should be used for parsing.\n * @default 'en-US'\n */\n locale: string\n}\n\n/**\n * Provides state management for a number field component. Number fields allow users to enter a number,\n * and increment or decrement the value using stepper buttons.\n */\nexport function useNumberFieldState(\n props: NumberFieldStateProps\n): NumberFieldState {\n let {\n minValue,\n maxValue,\n step,\n formatOptions,\n value,\n defaultValue,\n onChange,\n locale,\n isDisabled,\n isReadOnly\n } = props;\n\n let [numberValue, setNumberValue] = useControlledState<number>(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);\n let [inputValue, setInputValue] = useState(() => isNaN(numberValue) ? '' : new NumberFormatter(locale, formatOptions).format(numberValue));\n\n let numberParser = useMemo(() => new NumberParser(locale, formatOptions), [locale, formatOptions]);\n let numberingSystem = useMemo(() => numberParser.getNumberingSystem(inputValue), [numberParser, inputValue]);\n let formatter = useMemo(() => new NumberFormatter(locale, {...formatOptions, numberingSystem}), [locale, formatOptions, numberingSystem]);\n let intlOptions = useMemo(() => formatter.resolvedOptions(), [formatter]);\n let format = useCallback((value: number) => isNaN(value) ? '' : formatter.format(value), [formatter]);\n\n let clampStep = !isNaN(step) ? step : 1;\n if (intlOptions.style === 'percent' && isNaN(step)) {\n clampStep = 0.01;\n }\n\n // Update the input value when the number value or format options change. This is done\n // in a useEffect so that the controlled behavior is correct and we only update the\n // textfield after prop changes.\n let prevValue = useRef(numberValue);\n let prevLocale = useRef(locale);\n let prevFormatOptions = useRef(formatOptions);\n if (!Object.is(numberValue, prevValue.current) || locale !== prevLocale.current || formatOptions !== prevFormatOptions.current) {\n setInputValue(format(numberValue));\n prevValue.current = numberValue;\n prevLocale.current = locale;\n prevFormatOptions.current = formatOptions;\n }\n\n // Store last parsed value in a ref so it can be used by increment/decrement below\n let parsedValue = useMemo(() => numberParser.parse(inputValue), [numberParser, inputValue]);\n let parsed = useRef(0);\n parsed.current = parsedValue;\n\n let commit = () => {\n // Set to empty state if input value is empty\n if (!inputValue.length) {\n setNumberValue(NaN);\n setInputValue(value === undefined ? '' : format(numberValue));\n return;\n }\n\n // if it failed to parse, then reset input to formatted version of current number\n if (isNaN(parsed.current)) {\n setInputValue(format(numberValue));\n return;\n }\n\n // Clamp to min and max, round to the nearest step, and round to specified number of digits\n let clampedValue: number;\n if (isNaN(step)) {\n clampedValue = clamp(parsed.current, minValue, maxValue);\n } else {\n clampedValue = snapValueToStep(parsed.current, minValue, maxValue, step);\n }\n\n clampedValue = numberParser.parse(format(clampedValue));\n setNumberValue(clampedValue);\n\n // in a controlled state, the numberValue won't change, so we won't go back to our old input without help\n setInputValue(format(value === undefined ? clampedValue : numberValue));\n };\n\n let safeNextStep = (operation: '+' | '-', minMax: number) => {\n let prev = parsed.current;\n\n if (isNaN(prev)) {\n // if the input is empty, start from the min/max value when incrementing/decrementing,\n // or zero if there is no min/max value defined.\n let newValue = isNaN(minMax) ? 0 : minMax;\n return snapValueToStep(newValue, minValue, maxValue, clampStep);\n } else {\n // otherwise, first snap the current value to the nearest step. if it moves in the direction\n // we're going, use that value, otherwise add the step and snap that value.\n let newValue = snapValueToStep(prev, minValue, maxValue, clampStep);\n if ((operation === '+' && newValue > prev) || (operation === '-' && newValue < prev)) {\n return newValue;\n }\n\n return snapValueToStep(\n handleDecimalOperation(operation, prev, clampStep),\n minValue,\n maxValue,\n clampStep\n );\n }\n };\n\n let increment = () => {\n let newValue = safeNextStep('+', minValue);\n\n // if we've arrived at the same value that was previously in the state, the\n // input value should be updated to match\n // ex type 4, press increment, highlight the number in the input, type 4 again, press increment\n // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input\n if (newValue === numberValue) {\n setInputValue(format(newValue));\n }\n\n setNumberValue(newValue);\n };\n\n let decrement = () => {\n let newValue = safeNextStep('-', maxValue);\n\n if (newValue === numberValue) {\n setInputValue(format(newValue));\n }\n\n setNumberValue(newValue);\n };\n\n let incrementToMax = () => {\n if (maxValue != null) {\n setNumberValue(snapValueToStep(maxValue, minValue, maxValue, clampStep));\n }\n };\n\n let decrementToMin = () => {\n if (minValue != null) {\n setNumberValue(minValue);\n }\n };\n\n let canIncrement = useMemo(() => (\n !isDisabled &&\n !isReadOnly &&\n (\n isNaN(parsedValue) ||\n isNaN(maxValue) ||\n snapValueToStep(parsedValue, minValue, maxValue, clampStep) > parsedValue ||\n handleDecimalOperation('+', parsedValue, clampStep) <= maxValue\n )\n ), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);\n\n let canDecrement = useMemo(() => (\n !isDisabled &&\n !isReadOnly &&\n (\n isNaN(parsedValue) ||\n isNaN(minValue) ||\n snapValueToStep(parsedValue, minValue, maxValue, clampStep) < parsedValue ||\n handleDecimalOperation('-', parsedValue, clampStep) >= minValue\n )\n ), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);\n\n let validate = (value: string) => numberParser.isValidPartialNumber(value, minValue, maxValue);\n\n return {\n validate,\n increment,\n incrementToMax,\n decrement,\n decrementToMin,\n canIncrement,\n canDecrement,\n minValue,\n maxValue,\n numberValue: parsedValue,\n setInputValue,\n inputValue,\n commit\n };\n}\n\nfunction handleDecimalOperation(operator: '-' | '+', value1: number, value2: number): number {\n let result = operator === '+' ? value1 + value2 : value1 - value2;\n\n // Check if we have decimals\n if (value1 % 1 !== 0 || value2 % 1 !== 0) {\n const value1Decimal = value1.toString().split('.');\n const value2Decimal = value2.toString().split('.');\n const value1DecimalLength = (value1Decimal[1] && value1Decimal[1].length) || 0;\n const value2DecimalLength = (value2Decimal[1] && value2Decimal[1].length) || 0;\n const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength));\n\n // Transform the decimals to integers based on the precision\n value1 = Math.round(value1 * multiplier);\n value2 = Math.round(value2 * multiplier);\n\n // Perform the operation on integers values to make sure we don't get a fancy decimal value\n result = operator === '+' ? value1 + value2 : value1 - value2;\n\n // Transform the integer result back to decimal\n result /= multiplier;\n }\n\n return result;\n}\n"],"names":[],"version":3,"file":"module.js.map"}
@@ -1 +1 @@
1
- {"mappings":"A;AAiBA;IACE;A;A;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;A;A;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,4FAA4F;IAC5F,YAAY,EAAE,OAAO,CAAC;IACtB,4FAA4F;IAC5F,YAAY,EAAE,OAAO,CAAC;IACtB;A;A;A;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,gDAAgD;IAChD,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;A;A;A;A;OAKG;IACH,MAAM,IAAI,IAAI,CAAC;IACf,0FAA0F;IAC1F,SAAS,IAAI,IAAI,CAAC;IAClB,0FAA0F;IAC1F,SAAS,IAAI,IAAI,CAAC;IAClB,6EAA6E;IAC7E,cAAc,IAAI,IAAI,CAAC;IACvB,6EAA6E;IAC7E,cAAc,IAAI,IAAI,CAAA;CACvB;AAED,+BAAgC,SAAQ,gBAAgB;IACtD;A;A;OAGG;IACH,MAAM,EAAE,MAAM,CAAA;CACf;AAED;A;A;GAGG;AACH,oCACE,KAAK,EAAE,qBAAqB,GAC3B,gBAAgB,CA6KlB","sources":["./packages/@react-stately/numberfield/src/packages/@react-stately/numberfield/src/useNumberFieldState.ts","./packages/@react-stately/numberfield/src/packages/@react-stately/numberfield/src/index.ts"],"sourcesContent":[null,null],"names":[],"version":3,"file":"types.d.ts.map"}
1
+ {"mappings":";AAiBA;IACE;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,4FAA4F;IAC5F,YAAY,EAAE,OAAO,CAAC;IACtB,4FAA4F;IAC5F,YAAY,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,gDAAgD;IAChD,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;;;OAKG;IACH,MAAM,IAAI,IAAI,CAAC;IACf,0FAA0F;IAC1F,SAAS,IAAI,IAAI,CAAC;IAClB,0FAA0F;IAC1F,SAAS,IAAI,IAAI,CAAC;IAClB,6EAA6E;IAC7E,cAAc,IAAI,IAAI,CAAC;IACvB,6EAA6E;IAC7E,cAAc,IAAI,IAAI,CAAA;CACvB;AAED,+BAAgC,SAAQ,gBAAgB;IACtD;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,oCACE,KAAK,EAAE,qBAAqB,GAC3B,gBAAgB,CA+KlB","sources":["packages/@react-stately/numberfield/src/packages/@react-stately/numberfield/src/useNumberFieldState.ts","packages/@react-stately/numberfield/src/packages/@react-stately/numberfield/src/index.ts","packages/@react-stately/numberfield/src/index.ts"],"sourcesContent":[null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n/// <reference types=\"intl-types-extension\" />\n\nexport * from './useNumberFieldState';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-stately/numberfield",
3
- "version": "3.0.2",
3
+ "version": "3.0.5",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -18,10 +18,10 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "@babel/runtime": "^7.6.2",
21
- "@internationalized/number": "^3.0.2",
22
- "@react-stately/utils": "^3.2.2",
23
- "@react-types/numberfield": "^3.0.1",
24
- "@react-types/shared": "^3.8.0"
21
+ "@internationalized/number": "^3.0.5",
22
+ "@react-stately/utils": "^3.4.1",
23
+ "@react-types/numberfield": "^3.1.3",
24
+ "@react-types/shared": "^3.11.2"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "react": "^16.8.0 || ^17.0.0-rc.1"
@@ -29,5 +29,5 @@
29
29
  "publishConfig": {
30
30
  "access": "public"
31
31
  },
32
- "gitHead": "9204e1b8cb61dac767e91087fb16203611dc67c5"
32
+ "gitHead": "ed8d8d984c2f7f2c31e8b18795b97858a95e4729"
33
33
  }
@@ -13,7 +13,7 @@
13
13
  import {clamp, snapValueToStep, useControlledState} from '@react-stately/utils';
14
14
  import {NumberFieldProps} from '@react-types/numberfield';
15
15
  import {NumberFormatter, NumberParser} from '@internationalized/number';
16
- import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
16
+ import {useCallback, useMemo, useRef, useState} from 'react';
17
17
 
18
18
  export interface NumberFieldState {
19
19
  /**
@@ -104,9 +104,15 @@ export function useNumberFieldState(
104
104
  // Update the input value when the number value or format options change. This is done
105
105
  // in a useEffect so that the controlled behavior is correct and we only update the
106
106
  // textfield after prop changes.
107
- useEffect(() => {
107
+ let prevValue = useRef(numberValue);
108
+ let prevLocale = useRef(locale);
109
+ let prevFormatOptions = useRef(formatOptions);
110
+ if (!Object.is(numberValue, prevValue.current) || locale !== prevLocale.current || formatOptions !== prevFormatOptions.current) {
108
111
  setInputValue(format(numberValue));
109
- }, [numberValue, locale, formatOptions]);
112
+ prevValue.current = numberValue;
113
+ prevLocale.current = locale;
114
+ prevFormatOptions.current = formatOptions;
115
+ }
110
116
 
111
117
  // Store last parsed value in a ref so it can be used by increment/decrement below
112
118
  let parsedValue = useMemo(() => numberParser.parse(inputValue), [numberParser, inputValue]);
@@ -168,31 +174,27 @@ export function useNumberFieldState(
168
174
  };
169
175
 
170
176
  let increment = () => {
171
- setNumberValue((previousValue) => {
172
- let newValue = safeNextStep('+', minValue);
173
-
174
- // if we've arrived at the same value that was previously in the state, the
175
- // input value should be updated to match
176
- // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
177
- // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
178
- if (newValue === previousValue) {
179
- setInputValue(format(newValue));
180
- }
177
+ let newValue = safeNextStep('+', minValue);
178
+
179
+ // if we've arrived at the same value that was previously in the state, the
180
+ // input value should be updated to match
181
+ // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
182
+ // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
183
+ if (newValue === numberValue) {
184
+ setInputValue(format(newValue));
185
+ }
181
186
 
182
- return newValue;
183
- });
187
+ setNumberValue(newValue);
184
188
  };
185
189
 
186
190
  let decrement = () => {
187
- setNumberValue((previousValue) => {
188
- let newValue = safeNextStep('-', maxValue);
191
+ let newValue = safeNextStep('-', maxValue);
189
192
 
190
- if (newValue === previousValue) {
191
- setInputValue(format(newValue));
192
- }
193
+ if (newValue === numberValue) {
194
+ setInputValue(format(newValue));
195
+ }
193
196
 
194
- return newValue;
195
- });
197
+ setNumberValue(newValue);
196
198
  };
197
199
 
198
200
  let incrementToMax = () => {