@react-stately/numberfield 3.11.0 → 3.12.0

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/import.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import {useNumberFieldState as $de67e98908f0c6ee$export$7f629e9dc1ecf37c} from "./useNumberFieldState.mjs";
1
+ import {useNumberFieldState as $0868edeb6b3410e6$re_export$useNumberFieldState} from "react-stately/useNumberFieldState";
2
2
 
3
3
  /*
4
4
  * Copyright 2020 Adobe. All rights reserved.
@@ -13,5 +13,5 @@ import {useNumberFieldState as $de67e98908f0c6ee$export$7f629e9dc1ecf37c} from "
13
13
  */
14
14
 
15
15
 
16
- export {$de67e98908f0c6ee$export$7f629e9dc1ecf37c as useNumberFieldState};
16
+ export {$0868edeb6b3410e6$re_export$useNumberFieldState as useNumberFieldState};
17
17
  //# sourceMappingURL=module.js.map
package/dist/main.js CHANGED
@@ -1,11 +1,11 @@
1
- var $e18a693eeaf9c060$exports = require("./useNumberFieldState.main.js");
1
+ var $4q1YD$reactstatelyuseNumberFieldState = require("react-stately/useNumberFieldState");
2
2
 
3
3
 
4
4
  function $parcel$export(e, n, v, s) {
5
5
  Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
6
6
  }
7
7
 
8
- $parcel$export(module.exports, "useNumberFieldState", () => $e18a693eeaf9c060$exports.useNumberFieldState);
8
+ $parcel$export(module.exports, "useNumberFieldState", function () { return $4q1YD$reactstatelyuseNumberFieldState.useNumberFieldState; });
9
9
  /*
10
10
  * Copyright 2020 Adobe. All rights reserved.
11
11
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":";;;;;;;;AAAA;;;;;;;;;;CAUC","sources":["packages/@react-stately/numberfield/src/index.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\nexport {useNumberFieldState} from './useNumberFieldState';\n\nexport type {NumberFieldStateOptions} from './useNumberFieldState';\nexport type {NumberFieldState} from './useNumberFieldState';\n"],"names":[],"version":3,"file":"main.js.map"}
1
+ {"mappings":";;;;;;;;AAAA;;;;;;;;;;CAUC","sources":["packages/@react-stately/numberfield/src/index.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\nexport {useNumberFieldState} from 'react-stately/useNumberFieldState';\n\nexport type {NumberFieldStateOptions, NumberFieldProps, NumberFieldState} from 'react-stately/useNumberFieldState';\n"],"names":[],"version":3,"file":"main.js.map"}
package/dist/module.js CHANGED
@@ -1,4 +1,4 @@
1
- import {useNumberFieldState as $de67e98908f0c6ee$export$7f629e9dc1ecf37c} from "./useNumberFieldState.module.js";
1
+ import {useNumberFieldState as $0868edeb6b3410e6$re_export$useNumberFieldState} from "react-stately/useNumberFieldState";
2
2
 
3
3
  /*
4
4
  * Copyright 2020 Adobe. All rights reserved.
@@ -13,5 +13,5 @@ import {useNumberFieldState as $de67e98908f0c6ee$export$7f629e9dc1ecf37c} from "
13
13
  */
14
14
 
15
15
 
16
- export {$de67e98908f0c6ee$export$7f629e9dc1ecf37c as useNumberFieldState};
16
+ export {$0868edeb6b3410e6$re_export$useNumberFieldState as useNumberFieldState};
17
17
  //# sourceMappingURL=module.js.map
@@ -1 +1 @@
1
- {"mappings":";;AAAA;;;;;;;;;;CAUC","sources":["packages/@react-stately/numberfield/src/index.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\nexport {useNumberFieldState} from './useNumberFieldState';\n\nexport type {NumberFieldStateOptions} from './useNumberFieldState';\nexport type {NumberFieldState} from './useNumberFieldState';\n"],"names":[],"version":3,"file":"module.js.map"}
1
+ {"mappings":";;AAAA;;;;;;;;;;CAUC","sources":["packages/@react-stately/numberfield/src/index.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\nexport {useNumberFieldState} from 'react-stately/useNumberFieldState';\n\nexport type {NumberFieldStateOptions, NumberFieldProps, NumberFieldState} from 'react-stately/useNumberFieldState';\n"],"names":[],"version":3,"file":"module.js.map"}
@@ -0,0 +1,2 @@
1
+ export { useNumberFieldState } from 'react-stately/useNumberFieldState';
2
+ export type { NumberFieldStateOptions, NumberFieldProps, NumberFieldState } from 'react-stately/useNumberFieldState';
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@react-stately/numberfield",
3
- "version": "3.11.0",
3
+ "version": "3.12.0",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
7
7
  "module": "dist/module.js",
8
8
  "exports": {
9
- "source": "./src/index.ts",
10
- "types": [
11
- "./dist/types.d.ts",
12
- "./src/index.ts"
13
- ],
14
- "import": "./dist/import.mjs",
15
- "require": "./dist/main.js"
9
+ ".": {
10
+ "source": "./src/index.ts",
11
+ "types": "./dist/types/src/index.d.ts",
12
+ "import": "./dist/import.mjs",
13
+ "require": "./dist/main.js"
14
+ },
15
+ "./package.json": "./package.json"
16
16
  },
17
- "types": "dist/types.d.ts",
17
+ "types": "dist/types/src/index.d.ts",
18
18
  "source": "src/index.ts",
19
19
  "files": [
20
20
  "dist",
@@ -26,17 +26,18 @@
26
26
  "url": "https://github.com/adobe/react-spectrum"
27
27
  },
28
28
  "dependencies": {
29
- "@internationalized/number": "^3.6.5",
30
- "@react-stately/form": "^3.2.4",
31
- "@react-stately/utils": "^3.11.0",
32
- "@react-types/numberfield": "^3.8.18",
33
- "@swc/helpers": "^0.5.0"
29
+ "@swc/helpers": "^0.5.0",
30
+ "react-stately": "3.46.0"
34
31
  },
35
32
  "peerDependencies": {
36
- "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
33
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
34
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
37
35
  },
38
36
  "publishConfig": {
39
37
  "access": "public"
40
38
  },
41
- "gitHead": "8df187370053aa35f553cb388ad670f65e1ab371"
39
+ "targets": {
40
+ "types": false
41
+ },
42
+ "gitHead": "a6999bdf494a2e9c0381a5881908328bdd22ddae"
42
43
  }
package/src/index.ts CHANGED
@@ -10,7 +10,6 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- export {useNumberFieldState} from './useNumberFieldState';
13
+ export {useNumberFieldState} from 'react-stately/useNumberFieldState';
14
14
 
15
- export type {NumberFieldStateOptions} from './useNumberFieldState';
16
- export type {NumberFieldState} from './useNumberFieldState';
15
+ export type {NumberFieldStateOptions, NumberFieldProps, NumberFieldState} from 'react-stately/useNumberFieldState';
package/dist/types.d.ts DELETED
@@ -1,64 +0,0 @@
1
- import { FormValidationState } from "@react-stately/form";
2
- import { NumberFieldProps } from "@react-types/numberfield";
3
- export interface NumberFieldState extends FormValidationState {
4
- /**
5
- * The current text value of the input. Updated as the user types,
6
- * and formatted according to `formatOptions` on blur.
7
- */
8
- inputValue: string;
9
- /**
10
- * The currently parsed number value, or NaN if a valid number could not be parsed.
11
- * Updated based on the `inputValue` as the user types.
12
- */
13
- numberValue: number;
14
- /** The default value of the input. */
15
- defaultNumberValue: number;
16
- /** The minimum value of the number field. */
17
- minValue?: number;
18
- /** The maximum value of the number field. */
19
- maxValue?: number;
20
- /** Whether the current value can be incremented according to the maximum value and step. */
21
- canIncrement: boolean;
22
- /** Whether the current value can be decremented according to the minimum value and step. */
23
- canDecrement: boolean;
24
- /**
25
- * Validates a user input string according to the current locale and format options.
26
- * Values can be partially entered, and may be valid even if they cannot currently be parsed to a number.
27
- * Can be used to implement validation as a user types.
28
- */
29
- validate(value: string): boolean;
30
- /** Sets the current text value of the input. */
31
- setInputValue(val: string): void;
32
- /** Sets the number value. */
33
- setNumberValue(val: number): void;
34
- /**
35
- * Commits the current input value. The value is parsed to a number, clamped according
36
- * to the minimum and maximum values of the field, and snapped to the nearest step value.
37
- * This will fire the `onChange` prop with the new value, and if uncontrolled, update the `numberValue`.
38
- * Typically this is called when the field is blurred.
39
- * @param value - The value to commit. If not provided, the current input value is used.
40
- */
41
- commit(value?: string): void;
42
- /** Increments the current input value to the next step boundary, and fires `onChange`. */
43
- increment(): void;
44
- /** Decrements the current input value to the next step boundary, and fires `onChange`. */
45
- decrement(): void;
46
- /** Sets the current value to the `maxValue` if any, and fires `onChange`. */
47
- incrementToMax(): void;
48
- /** Sets the current value to the `minValue` if any, and fires `onChange`. */
49
- decrementToMin(): void;
50
- }
51
- export interface NumberFieldStateOptions extends NumberFieldProps {
52
- /**
53
- * The locale that should be used for parsing.
54
- * @default 'en-US'
55
- */
56
- locale: string;
57
- }
58
- /**
59
- * Provides state management for a number field component. Number fields allow users to enter a number,
60
- * and increment or decrement the value using stepper buttons.
61
- */
62
- export function useNumberFieldState(props: NumberFieldStateOptions): NumberFieldState;
63
-
64
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"mappings":";;AAkBA,iCAAkC,SAAQ,mBAAmB;IAC3D;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,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,6BAA6B;IAC7B,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,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,wCAAyC,SAAQ,gBAAgB;IAC/D;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,oCACE,KAAK,EAAE,uBAAuB,GAC7B,gBAAgB,CAkNlB","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\nexport {useNumberFieldState} from './useNumberFieldState';\n\nexport type {NumberFieldStateOptions} from './useNumberFieldState';\nexport type {NumberFieldState} from './useNumberFieldState';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
@@ -1,209 +0,0 @@
1
- var $gPCRT$reactstatelyutils = require("@react-stately/utils");
2
- var $gPCRT$reactstatelyform = require("@react-stately/form");
3
- var $gPCRT$internationalizednumber = require("@internationalized/number");
4
- var $gPCRT$react = require("react");
5
-
6
-
7
- function $parcel$export(e, n, v, s) {
8
- Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
9
- }
10
-
11
- $parcel$export(module.exports, "useNumberFieldState", () => $e18a693eeaf9c060$export$7f629e9dc1ecf37c);
12
- /*
13
- * Copyright 2020 Adobe. All rights reserved.
14
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
15
- * you may not use this file except in compliance with the License. You may obtain a copy
16
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
17
- *
18
- * Unless required by applicable law or agreed to in writing, software distributed under
19
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
20
- * OF ANY KIND, either express or implied. See the License for the specific language
21
- * governing permissions and limitations under the License.
22
- */
23
-
24
-
25
-
26
- function $e18a693eeaf9c060$export$7f629e9dc1ecf37c(props) {
27
- let { minValue: minValue, maxValue: maxValue, step: step, formatOptions: formatOptions, value: value, defaultValue: defaultValue = NaN, onChange: onChange, locale: locale, isDisabled: isDisabled, isReadOnly: isReadOnly } = props;
28
- if (value === null) value = NaN;
29
- if (value !== undefined && !isNaN(value)) {
30
- if (step !== undefined && !isNaN(step)) value = (0, $gPCRT$reactstatelyutils.snapValueToStep)(value, minValue, maxValue, step);
31
- else value = (0, $gPCRT$reactstatelyutils.clamp)(value, minValue, maxValue);
32
- }
33
- if (!isNaN(defaultValue)) {
34
- if (step !== undefined && !isNaN(step)) defaultValue = (0, $gPCRT$reactstatelyutils.snapValueToStep)(defaultValue, minValue, maxValue, step);
35
- else defaultValue = (0, $gPCRT$reactstatelyutils.clamp)(defaultValue, minValue, maxValue);
36
- }
37
- let [numberValue, setNumberValue] = (0, $gPCRT$reactstatelyutils.useControlledState)(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);
38
- let [initialValue] = (0, $gPCRT$react.useState)(numberValue);
39
- let [inputValue, setInputValue] = (0, $gPCRT$react.useState)(()=>isNaN(numberValue) ? '' : new (0, $gPCRT$internationalizednumber.NumberFormatter)(locale, formatOptions).format(numberValue));
40
- let numberParser = (0, $gPCRT$react.useMemo)(()=>new (0, $gPCRT$internationalizednumber.NumberParser)(locale, formatOptions), [
41
- locale,
42
- formatOptions
43
- ]);
44
- let numberingSystem = (0, $gPCRT$react.useMemo)(()=>numberParser.getNumberingSystem(inputValue), [
45
- numberParser,
46
- inputValue
47
- ]);
48
- let formatter = (0, $gPCRT$react.useMemo)(()=>new (0, $gPCRT$internationalizednumber.NumberFormatter)(locale, {
49
- ...formatOptions,
50
- numberingSystem: numberingSystem
51
- }), [
52
- locale,
53
- formatOptions,
54
- numberingSystem
55
- ]);
56
- let intlOptions = (0, $gPCRT$react.useMemo)(()=>formatter.resolvedOptions(), [
57
- formatter
58
- ]);
59
- let format = (0, $gPCRT$react.useCallback)((value)=>isNaN(value) || value === null ? '' : formatter.format(value), [
60
- formatter
61
- ]);
62
- let validation = (0, $gPCRT$reactstatelyform.useFormValidationState)({
63
- ...props,
64
- value: numberValue
65
- });
66
- let clampStep = step !== undefined && !isNaN(step) ? step : 1;
67
- if (intlOptions.style === 'percent' && (step === undefined || isNaN(step))) clampStep = 0.01;
68
- // Update the input value when the number value or format options change. This is done
69
- // in a useEffect so that the controlled behavior is correct and we only update the
70
- // textfield after prop changes.
71
- let [prevValue, setPrevValue] = (0, $gPCRT$react.useState)(numberValue);
72
- let [prevLocale, setPrevLocale] = (0, $gPCRT$react.useState)(locale);
73
- let [prevFormatOptions, setPrevFormatOptions] = (0, $gPCRT$react.useState)(formatOptions);
74
- if (!Object.is(numberValue, prevValue) || locale !== prevLocale || formatOptions !== prevFormatOptions) {
75
- setInputValue(format(numberValue));
76
- setPrevValue(numberValue);
77
- setPrevLocale(locale);
78
- setPrevFormatOptions(formatOptions);
79
- }
80
- let parsedValue = (0, $gPCRT$react.useMemo)(()=>numberParser.parse(inputValue), [
81
- numberParser,
82
- inputValue
83
- ]);
84
- let commit = (overrideValue)=>{
85
- let newInputValue = overrideValue === undefined ? inputValue : overrideValue;
86
- let newParsedValue = parsedValue;
87
- if (overrideValue !== undefined) newParsedValue = numberParser.parse(newInputValue);
88
- // Set to empty state if input value is empty
89
- if (!newInputValue.length) {
90
- setNumberValue(NaN);
91
- setInputValue(value === undefined ? '' : format(numberValue));
92
- return;
93
- }
94
- // if it failed to parse, then reset input to formatted version of current number
95
- if (isNaN(newParsedValue)) {
96
- setInputValue(format(numberValue));
97
- return;
98
- }
99
- // Clamp to min and max, round to the nearest step, and round to specified number of digits
100
- let clampedValue;
101
- if (step === undefined || isNaN(step)) clampedValue = (0, $gPCRT$reactstatelyutils.clamp)(newParsedValue, minValue, maxValue);
102
- else clampedValue = (0, $gPCRT$reactstatelyutils.snapValueToStep)(newParsedValue, minValue, maxValue, step);
103
- clampedValue = numberParser.parse(format(clampedValue));
104
- setNumberValue(clampedValue);
105
- // in a controlled state, the numberValue won't change, so we won't go back to our old input without help
106
- setInputValue(format(value === undefined ? clampedValue : numberValue));
107
- validation.commitValidation();
108
- };
109
- let safeNextStep = (operation, minMax = 0)=>{
110
- let prev = parsedValue;
111
- if (isNaN(prev)) {
112
- // if the input is empty, start from the min/max value when incrementing/decrementing,
113
- // or zero if there is no min/max value defined.
114
- let newValue = isNaN(minMax) ? 0 : minMax;
115
- return (0, $gPCRT$reactstatelyutils.snapValueToStep)(newValue, minValue, maxValue, clampStep);
116
- } else {
117
- // otherwise, first snap the current value to the nearest step. if it moves in the direction
118
- // we're going, use that value, otherwise add the step and snap that value.
119
- let newValue = (0, $gPCRT$reactstatelyutils.snapValueToStep)(prev, minValue, maxValue, clampStep);
120
- if (operation === '+' && newValue > prev || operation === '-' && newValue < prev) return newValue;
121
- return (0, $gPCRT$reactstatelyutils.snapValueToStep)($e18a693eeaf9c060$var$handleDecimalOperation(operation, prev, clampStep), minValue, maxValue, clampStep);
122
- }
123
- };
124
- let increment = ()=>{
125
- let newValue = safeNextStep('+', minValue);
126
- // if we've arrived at the same value that was previously in the state, the
127
- // input value should be updated to match
128
- // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
129
- // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
130
- if (newValue === numberValue) setInputValue(format(newValue));
131
- setNumberValue(newValue);
132
- validation.commitValidation();
133
- };
134
- let decrement = ()=>{
135
- let newValue = safeNextStep('-', maxValue);
136
- if (newValue === numberValue) setInputValue(format(newValue));
137
- setNumberValue(newValue);
138
- validation.commitValidation();
139
- };
140
- let incrementToMax = ()=>{
141
- if (maxValue != null) {
142
- setNumberValue((0, $gPCRT$reactstatelyutils.snapValueToStep)(maxValue, minValue, maxValue, clampStep));
143
- validation.commitValidation();
144
- }
145
- };
146
- let decrementToMin = ()=>{
147
- if (minValue != null) {
148
- setNumberValue(minValue);
149
- validation.commitValidation();
150
- }
151
- };
152
- let canIncrement = (0, $gPCRT$react.useMemo)(()=>!isDisabled && !isReadOnly && (isNaN(parsedValue) || maxValue === undefined || isNaN(maxValue) || (0, $gPCRT$reactstatelyutils.snapValueToStep)(parsedValue, minValue, maxValue, clampStep) > parsedValue || $e18a693eeaf9c060$var$handleDecimalOperation('+', parsedValue, clampStep) <= maxValue), [
153
- isDisabled,
154
- isReadOnly,
155
- minValue,
156
- maxValue,
157
- clampStep,
158
- parsedValue
159
- ]);
160
- let canDecrement = (0, $gPCRT$react.useMemo)(()=>!isDisabled && !isReadOnly && (isNaN(parsedValue) || minValue === undefined || isNaN(minValue) || (0, $gPCRT$reactstatelyutils.snapValueToStep)(parsedValue, minValue, maxValue, clampStep) < parsedValue || $e18a693eeaf9c060$var$handleDecimalOperation('-', parsedValue, clampStep) >= minValue), [
161
- isDisabled,
162
- isReadOnly,
163
- minValue,
164
- maxValue,
165
- clampStep,
166
- parsedValue
167
- ]);
168
- let validate = (value)=>numberParser.isValidPartialNumber(value, minValue, maxValue);
169
- return {
170
- ...validation,
171
- validate: validate,
172
- increment: increment,
173
- incrementToMax: incrementToMax,
174
- decrement: decrement,
175
- decrementToMin: decrementToMin,
176
- canIncrement: canIncrement,
177
- canDecrement: canDecrement,
178
- minValue: minValue,
179
- maxValue: maxValue,
180
- numberValue: parsedValue,
181
- defaultNumberValue: isNaN(defaultValue) ? initialValue : defaultValue,
182
- setNumberValue: setNumberValue,
183
- setInputValue: setInputValue,
184
- inputValue: inputValue,
185
- commit: commit
186
- };
187
- }
188
- function $e18a693eeaf9c060$var$handleDecimalOperation(operator, value1, value2) {
189
- let result = operator === '+' ? value1 + value2 : value1 - value2;
190
- // Check if we have decimals
191
- if (value1 % 1 !== 0 || value2 % 1 !== 0) {
192
- const value1Decimal = value1.toString().split('.');
193
- const value2Decimal = value2.toString().split('.');
194
- const value1DecimalLength = value1Decimal[1] && value1Decimal[1].length || 0;
195
- const value2DecimalLength = value2Decimal[1] && value2Decimal[1].length || 0;
196
- const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength));
197
- // Transform the decimals to integers based on the precision
198
- value1 = Math.round(value1 * multiplier);
199
- value2 = Math.round(value2 * multiplier);
200
- // Perform the operation on integers values to make sure we don't get a fancy decimal value
201
- result = operator === '+' ? value1 + value2 : value1 - value2;
202
- // Transform the integer result back to decimal
203
- result /= multiplier;
204
- }
205
- return result;
206
- }
207
-
208
-
209
- //# sourceMappingURL=useNumberFieldState.main.js.map
@@ -1 +0,0 @@
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 {FormValidationState, useFormValidationState} from '@react-stately/form';\nimport {NumberFieldProps} from '@react-types/numberfield';\nimport {NumberFormatter, NumberParser} from '@internationalized/number';\nimport {useCallback, useMemo, useState} from 'react';\n\nexport interface NumberFieldState extends FormValidationState {\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 default value of the input. */\n defaultNumberValue: 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 /** Sets the number value. */\n setNumberValue(val: number): 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 * @param value - The value to commit. If not provided, the current input value is used.\n */\n commit(value?: string): 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\nexport interface NumberFieldStateOptions 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: NumberFieldStateOptions\n): NumberFieldState {\n let {\n minValue,\n maxValue,\n step,\n formatOptions,\n value,\n defaultValue = NaN,\n onChange,\n locale,\n isDisabled,\n isReadOnly\n } = props;\n\n if (value === null) {\n value = NaN;\n }\n\n if (value !== undefined && !isNaN(value)) {\n if (step !== undefined && !isNaN(step)) {\n value = snapValueToStep(value, minValue, maxValue, step);\n } else {\n value = clamp(value, minValue, maxValue);\n }\n }\n\n if (!isNaN(defaultValue)) {\n if (step !== undefined && !isNaN(step)) {\n defaultValue = snapValueToStep(defaultValue, minValue, maxValue, step);\n } else {\n defaultValue = clamp(defaultValue, minValue, maxValue);\n }\n }\n\n let [numberValue, setNumberValue] = useControlledState<number>(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);\n let [initialValue] = useState(numberValue);\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) || value === null) ? '' : formatter.format(value), [formatter]);\n\n let validation = useFormValidationState({\n ...props,\n value: numberValue\n });\n\n let clampStep = (step !== undefined && !isNaN(step)) ? step : 1;\n if (intlOptions.style === 'percent' && (step === undefined || 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, setPrevValue] = useState(numberValue);\n let [prevLocale, setPrevLocale] = useState(locale);\n let [prevFormatOptions, setPrevFormatOptions] = useState(formatOptions);\n if (!Object.is(numberValue, prevValue) || locale !== prevLocale || formatOptions !== prevFormatOptions) {\n setInputValue(format(numberValue));\n setPrevValue(numberValue);\n setPrevLocale(locale);\n setPrevFormatOptions(formatOptions);\n }\n\n let parsedValue = useMemo(() => numberParser.parse(inputValue), [numberParser, inputValue]);\n let commit = (overrideValue?: string) => {\n let newInputValue = overrideValue === undefined ? inputValue : overrideValue;\n let newParsedValue = parsedValue;\n if (overrideValue !== undefined) {\n newParsedValue = numberParser.parse(newInputValue);\n }\n // Set to empty state if input value is empty\n if (!newInputValue.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(newParsedValue)) {\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 (step === undefined || isNaN(step)) {\n clampedValue = clamp(newParsedValue, minValue, maxValue);\n } else {\n clampedValue = snapValueToStep(newParsedValue, 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 validation.commitValidation();\n };\n\n let safeNextStep = (operation: '+' | '-', minMax: number = 0) => {\n let prev = parsedValue;\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 validation.commitValidation();\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 validation.commitValidation();\n };\n\n let incrementToMax = () => {\n if (maxValue != null) {\n setNumberValue(snapValueToStep(maxValue, minValue, maxValue, clampStep));\n validation.commitValidation();\n }\n };\n\n let decrementToMin = () => {\n if (minValue != null) {\n setNumberValue(minValue);\n validation.commitValidation();\n }\n };\n\n let canIncrement = useMemo(() => (\n !isDisabled &&\n !isReadOnly &&\n (\n isNaN(parsedValue) ||\n (maxValue === undefined || 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 (minValue === undefined || 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 ...validation,\n validate,\n increment,\n incrementToMax,\n decrement,\n decrementToMin,\n canIncrement,\n canDecrement,\n minValue,\n maxValue,\n numberValue: parsedValue,\n defaultNumberValue: isNaN(defaultValue) ? initialValue : defaultValue,\n setNumberValue,\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":"useNumberFieldState.main.js.map"}
@@ -1,204 +0,0 @@
1
- import {snapValueToStep as $kNCPO$snapValueToStep, clamp as $kNCPO$clamp, useControlledState as $kNCPO$useControlledState} from "@react-stately/utils";
2
- import {useFormValidationState as $kNCPO$useFormValidationState} from "@react-stately/form";
3
- import {NumberFormatter as $kNCPO$NumberFormatter, NumberParser as $kNCPO$NumberParser} from "@internationalized/number";
4
- import {useState as $kNCPO$useState, useMemo as $kNCPO$useMemo, useCallback as $kNCPO$useCallback} from "react";
5
-
6
- /*
7
- * Copyright 2020 Adobe. All rights reserved.
8
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
9
- * you may not use this file except in compliance with the License. You may obtain a copy
10
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
11
- *
12
- * Unless required by applicable law or agreed to in writing, software distributed under
13
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
14
- * OF ANY KIND, either express or implied. See the License for the specific language
15
- * governing permissions and limitations under the License.
16
- */
17
-
18
-
19
-
20
- function $de67e98908f0c6ee$export$7f629e9dc1ecf37c(props) {
21
- let { minValue: minValue, maxValue: maxValue, step: step, formatOptions: formatOptions, value: value, defaultValue: defaultValue = NaN, onChange: onChange, locale: locale, isDisabled: isDisabled, isReadOnly: isReadOnly } = props;
22
- if (value === null) value = NaN;
23
- if (value !== undefined && !isNaN(value)) {
24
- if (step !== undefined && !isNaN(step)) value = (0, $kNCPO$snapValueToStep)(value, minValue, maxValue, step);
25
- else value = (0, $kNCPO$clamp)(value, minValue, maxValue);
26
- }
27
- if (!isNaN(defaultValue)) {
28
- if (step !== undefined && !isNaN(step)) defaultValue = (0, $kNCPO$snapValueToStep)(defaultValue, minValue, maxValue, step);
29
- else defaultValue = (0, $kNCPO$clamp)(defaultValue, minValue, maxValue);
30
- }
31
- let [numberValue, setNumberValue] = (0, $kNCPO$useControlledState)(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);
32
- let [initialValue] = (0, $kNCPO$useState)(numberValue);
33
- let [inputValue, setInputValue] = (0, $kNCPO$useState)(()=>isNaN(numberValue) ? '' : new (0, $kNCPO$NumberFormatter)(locale, formatOptions).format(numberValue));
34
- let numberParser = (0, $kNCPO$useMemo)(()=>new (0, $kNCPO$NumberParser)(locale, formatOptions), [
35
- locale,
36
- formatOptions
37
- ]);
38
- let numberingSystem = (0, $kNCPO$useMemo)(()=>numberParser.getNumberingSystem(inputValue), [
39
- numberParser,
40
- inputValue
41
- ]);
42
- let formatter = (0, $kNCPO$useMemo)(()=>new (0, $kNCPO$NumberFormatter)(locale, {
43
- ...formatOptions,
44
- numberingSystem: numberingSystem
45
- }), [
46
- locale,
47
- formatOptions,
48
- numberingSystem
49
- ]);
50
- let intlOptions = (0, $kNCPO$useMemo)(()=>formatter.resolvedOptions(), [
51
- formatter
52
- ]);
53
- let format = (0, $kNCPO$useCallback)((value)=>isNaN(value) || value === null ? '' : formatter.format(value), [
54
- formatter
55
- ]);
56
- let validation = (0, $kNCPO$useFormValidationState)({
57
- ...props,
58
- value: numberValue
59
- });
60
- let clampStep = step !== undefined && !isNaN(step) ? step : 1;
61
- if (intlOptions.style === 'percent' && (step === undefined || isNaN(step))) clampStep = 0.01;
62
- // Update the input value when the number value or format options change. This is done
63
- // in a useEffect so that the controlled behavior is correct and we only update the
64
- // textfield after prop changes.
65
- let [prevValue, setPrevValue] = (0, $kNCPO$useState)(numberValue);
66
- let [prevLocale, setPrevLocale] = (0, $kNCPO$useState)(locale);
67
- let [prevFormatOptions, setPrevFormatOptions] = (0, $kNCPO$useState)(formatOptions);
68
- if (!Object.is(numberValue, prevValue) || locale !== prevLocale || formatOptions !== prevFormatOptions) {
69
- setInputValue(format(numberValue));
70
- setPrevValue(numberValue);
71
- setPrevLocale(locale);
72
- setPrevFormatOptions(formatOptions);
73
- }
74
- let parsedValue = (0, $kNCPO$useMemo)(()=>numberParser.parse(inputValue), [
75
- numberParser,
76
- inputValue
77
- ]);
78
- let commit = (overrideValue)=>{
79
- let newInputValue = overrideValue === undefined ? inputValue : overrideValue;
80
- let newParsedValue = parsedValue;
81
- if (overrideValue !== undefined) newParsedValue = numberParser.parse(newInputValue);
82
- // Set to empty state if input value is empty
83
- if (!newInputValue.length) {
84
- setNumberValue(NaN);
85
- setInputValue(value === undefined ? '' : format(numberValue));
86
- return;
87
- }
88
- // if it failed to parse, then reset input to formatted version of current number
89
- if (isNaN(newParsedValue)) {
90
- setInputValue(format(numberValue));
91
- return;
92
- }
93
- // Clamp to min and max, round to the nearest step, and round to specified number of digits
94
- let clampedValue;
95
- if (step === undefined || isNaN(step)) clampedValue = (0, $kNCPO$clamp)(newParsedValue, minValue, maxValue);
96
- else clampedValue = (0, $kNCPO$snapValueToStep)(newParsedValue, minValue, maxValue, step);
97
- clampedValue = numberParser.parse(format(clampedValue));
98
- setNumberValue(clampedValue);
99
- // in a controlled state, the numberValue won't change, so we won't go back to our old input without help
100
- setInputValue(format(value === undefined ? clampedValue : numberValue));
101
- validation.commitValidation();
102
- };
103
- let safeNextStep = (operation, minMax = 0)=>{
104
- let prev = parsedValue;
105
- if (isNaN(prev)) {
106
- // if the input is empty, start from the min/max value when incrementing/decrementing,
107
- // or zero if there is no min/max value defined.
108
- let newValue = isNaN(minMax) ? 0 : minMax;
109
- return (0, $kNCPO$snapValueToStep)(newValue, minValue, maxValue, clampStep);
110
- } else {
111
- // otherwise, first snap the current value to the nearest step. if it moves in the direction
112
- // we're going, use that value, otherwise add the step and snap that value.
113
- let newValue = (0, $kNCPO$snapValueToStep)(prev, minValue, maxValue, clampStep);
114
- if (operation === '+' && newValue > prev || operation === '-' && newValue < prev) return newValue;
115
- return (0, $kNCPO$snapValueToStep)($de67e98908f0c6ee$var$handleDecimalOperation(operation, prev, clampStep), minValue, maxValue, clampStep);
116
- }
117
- };
118
- let increment = ()=>{
119
- let newValue = safeNextStep('+', minValue);
120
- // if we've arrived at the same value that was previously in the state, the
121
- // input value should be updated to match
122
- // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
123
- // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
124
- if (newValue === numberValue) setInputValue(format(newValue));
125
- setNumberValue(newValue);
126
- validation.commitValidation();
127
- };
128
- let decrement = ()=>{
129
- let newValue = safeNextStep('-', maxValue);
130
- if (newValue === numberValue) setInputValue(format(newValue));
131
- setNumberValue(newValue);
132
- validation.commitValidation();
133
- };
134
- let incrementToMax = ()=>{
135
- if (maxValue != null) {
136
- setNumberValue((0, $kNCPO$snapValueToStep)(maxValue, minValue, maxValue, clampStep));
137
- validation.commitValidation();
138
- }
139
- };
140
- let decrementToMin = ()=>{
141
- if (minValue != null) {
142
- setNumberValue(minValue);
143
- validation.commitValidation();
144
- }
145
- };
146
- let canIncrement = (0, $kNCPO$useMemo)(()=>!isDisabled && !isReadOnly && (isNaN(parsedValue) || maxValue === undefined || isNaN(maxValue) || (0, $kNCPO$snapValueToStep)(parsedValue, minValue, maxValue, clampStep) > parsedValue || $de67e98908f0c6ee$var$handleDecimalOperation('+', parsedValue, clampStep) <= maxValue), [
147
- isDisabled,
148
- isReadOnly,
149
- minValue,
150
- maxValue,
151
- clampStep,
152
- parsedValue
153
- ]);
154
- let canDecrement = (0, $kNCPO$useMemo)(()=>!isDisabled && !isReadOnly && (isNaN(parsedValue) || minValue === undefined || isNaN(minValue) || (0, $kNCPO$snapValueToStep)(parsedValue, minValue, maxValue, clampStep) < parsedValue || $de67e98908f0c6ee$var$handleDecimalOperation('-', parsedValue, clampStep) >= minValue), [
155
- isDisabled,
156
- isReadOnly,
157
- minValue,
158
- maxValue,
159
- clampStep,
160
- parsedValue
161
- ]);
162
- let validate = (value)=>numberParser.isValidPartialNumber(value, minValue, maxValue);
163
- return {
164
- ...validation,
165
- validate: validate,
166
- increment: increment,
167
- incrementToMax: incrementToMax,
168
- decrement: decrement,
169
- decrementToMin: decrementToMin,
170
- canIncrement: canIncrement,
171
- canDecrement: canDecrement,
172
- minValue: minValue,
173
- maxValue: maxValue,
174
- numberValue: parsedValue,
175
- defaultNumberValue: isNaN(defaultValue) ? initialValue : defaultValue,
176
- setNumberValue: setNumberValue,
177
- setInputValue: setInputValue,
178
- inputValue: inputValue,
179
- commit: commit
180
- };
181
- }
182
- function $de67e98908f0c6ee$var$handleDecimalOperation(operator, value1, value2) {
183
- let result = operator === '+' ? value1 + value2 : value1 - value2;
184
- // Check if we have decimals
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));
191
- // Transform the decimals to integers based on the precision
192
- value1 = Math.round(value1 * multiplier);
193
- value2 = Math.round(value2 * multiplier);
194
- // Perform the operation on integers values to make sure we don't get a fancy decimal value
195
- result = operator === '+' ? value1 + value2 : value1 - value2;
196
- // Transform the integer result back to decimal
197
- result /= multiplier;
198
- }
199
- return result;
200
- }
201
-
202
-
203
- export {$de67e98908f0c6ee$export$7f629e9dc1ecf37c as useNumberFieldState};
204
- //# sourceMappingURL=useNumberFieldState.module.js.map
@@ -1,204 +0,0 @@
1
- import {snapValueToStep as $kNCPO$snapValueToStep, clamp as $kNCPO$clamp, useControlledState as $kNCPO$useControlledState} from "@react-stately/utils";
2
- import {useFormValidationState as $kNCPO$useFormValidationState} from "@react-stately/form";
3
- import {NumberFormatter as $kNCPO$NumberFormatter, NumberParser as $kNCPO$NumberParser} from "@internationalized/number";
4
- import {useState as $kNCPO$useState, useMemo as $kNCPO$useMemo, useCallback as $kNCPO$useCallback} from "react";
5
-
6
- /*
7
- * Copyright 2020 Adobe. All rights reserved.
8
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
9
- * you may not use this file except in compliance with the License. You may obtain a copy
10
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
11
- *
12
- * Unless required by applicable law or agreed to in writing, software distributed under
13
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
14
- * OF ANY KIND, either express or implied. See the License for the specific language
15
- * governing permissions and limitations under the License.
16
- */
17
-
18
-
19
-
20
- function $de67e98908f0c6ee$export$7f629e9dc1ecf37c(props) {
21
- let { minValue: minValue, maxValue: maxValue, step: step, formatOptions: formatOptions, value: value, defaultValue: defaultValue = NaN, onChange: onChange, locale: locale, isDisabled: isDisabled, isReadOnly: isReadOnly } = props;
22
- if (value === null) value = NaN;
23
- if (value !== undefined && !isNaN(value)) {
24
- if (step !== undefined && !isNaN(step)) value = (0, $kNCPO$snapValueToStep)(value, minValue, maxValue, step);
25
- else value = (0, $kNCPO$clamp)(value, minValue, maxValue);
26
- }
27
- if (!isNaN(defaultValue)) {
28
- if (step !== undefined && !isNaN(step)) defaultValue = (0, $kNCPO$snapValueToStep)(defaultValue, minValue, maxValue, step);
29
- else defaultValue = (0, $kNCPO$clamp)(defaultValue, minValue, maxValue);
30
- }
31
- let [numberValue, setNumberValue] = (0, $kNCPO$useControlledState)(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);
32
- let [initialValue] = (0, $kNCPO$useState)(numberValue);
33
- let [inputValue, setInputValue] = (0, $kNCPO$useState)(()=>isNaN(numberValue) ? '' : new (0, $kNCPO$NumberFormatter)(locale, formatOptions).format(numberValue));
34
- let numberParser = (0, $kNCPO$useMemo)(()=>new (0, $kNCPO$NumberParser)(locale, formatOptions), [
35
- locale,
36
- formatOptions
37
- ]);
38
- let numberingSystem = (0, $kNCPO$useMemo)(()=>numberParser.getNumberingSystem(inputValue), [
39
- numberParser,
40
- inputValue
41
- ]);
42
- let formatter = (0, $kNCPO$useMemo)(()=>new (0, $kNCPO$NumberFormatter)(locale, {
43
- ...formatOptions,
44
- numberingSystem: numberingSystem
45
- }), [
46
- locale,
47
- formatOptions,
48
- numberingSystem
49
- ]);
50
- let intlOptions = (0, $kNCPO$useMemo)(()=>formatter.resolvedOptions(), [
51
- formatter
52
- ]);
53
- let format = (0, $kNCPO$useCallback)((value)=>isNaN(value) || value === null ? '' : formatter.format(value), [
54
- formatter
55
- ]);
56
- let validation = (0, $kNCPO$useFormValidationState)({
57
- ...props,
58
- value: numberValue
59
- });
60
- let clampStep = step !== undefined && !isNaN(step) ? step : 1;
61
- if (intlOptions.style === 'percent' && (step === undefined || isNaN(step))) clampStep = 0.01;
62
- // Update the input value when the number value or format options change. This is done
63
- // in a useEffect so that the controlled behavior is correct and we only update the
64
- // textfield after prop changes.
65
- let [prevValue, setPrevValue] = (0, $kNCPO$useState)(numberValue);
66
- let [prevLocale, setPrevLocale] = (0, $kNCPO$useState)(locale);
67
- let [prevFormatOptions, setPrevFormatOptions] = (0, $kNCPO$useState)(formatOptions);
68
- if (!Object.is(numberValue, prevValue) || locale !== prevLocale || formatOptions !== prevFormatOptions) {
69
- setInputValue(format(numberValue));
70
- setPrevValue(numberValue);
71
- setPrevLocale(locale);
72
- setPrevFormatOptions(formatOptions);
73
- }
74
- let parsedValue = (0, $kNCPO$useMemo)(()=>numberParser.parse(inputValue), [
75
- numberParser,
76
- inputValue
77
- ]);
78
- let commit = (overrideValue)=>{
79
- let newInputValue = overrideValue === undefined ? inputValue : overrideValue;
80
- let newParsedValue = parsedValue;
81
- if (overrideValue !== undefined) newParsedValue = numberParser.parse(newInputValue);
82
- // Set to empty state if input value is empty
83
- if (!newInputValue.length) {
84
- setNumberValue(NaN);
85
- setInputValue(value === undefined ? '' : format(numberValue));
86
- return;
87
- }
88
- // if it failed to parse, then reset input to formatted version of current number
89
- if (isNaN(newParsedValue)) {
90
- setInputValue(format(numberValue));
91
- return;
92
- }
93
- // Clamp to min and max, round to the nearest step, and round to specified number of digits
94
- let clampedValue;
95
- if (step === undefined || isNaN(step)) clampedValue = (0, $kNCPO$clamp)(newParsedValue, minValue, maxValue);
96
- else clampedValue = (0, $kNCPO$snapValueToStep)(newParsedValue, minValue, maxValue, step);
97
- clampedValue = numberParser.parse(format(clampedValue));
98
- setNumberValue(clampedValue);
99
- // in a controlled state, the numberValue won't change, so we won't go back to our old input without help
100
- setInputValue(format(value === undefined ? clampedValue : numberValue));
101
- validation.commitValidation();
102
- };
103
- let safeNextStep = (operation, minMax = 0)=>{
104
- let prev = parsedValue;
105
- if (isNaN(prev)) {
106
- // if the input is empty, start from the min/max value when incrementing/decrementing,
107
- // or zero if there is no min/max value defined.
108
- let newValue = isNaN(minMax) ? 0 : minMax;
109
- return (0, $kNCPO$snapValueToStep)(newValue, minValue, maxValue, clampStep);
110
- } else {
111
- // otherwise, first snap the current value to the nearest step. if it moves in the direction
112
- // we're going, use that value, otherwise add the step and snap that value.
113
- let newValue = (0, $kNCPO$snapValueToStep)(prev, minValue, maxValue, clampStep);
114
- if (operation === '+' && newValue > prev || operation === '-' && newValue < prev) return newValue;
115
- return (0, $kNCPO$snapValueToStep)($de67e98908f0c6ee$var$handleDecimalOperation(operation, prev, clampStep), minValue, maxValue, clampStep);
116
- }
117
- };
118
- let increment = ()=>{
119
- let newValue = safeNextStep('+', minValue);
120
- // if we've arrived at the same value that was previously in the state, the
121
- // input value should be updated to match
122
- // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
123
- // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
124
- if (newValue === numberValue) setInputValue(format(newValue));
125
- setNumberValue(newValue);
126
- validation.commitValidation();
127
- };
128
- let decrement = ()=>{
129
- let newValue = safeNextStep('-', maxValue);
130
- if (newValue === numberValue) setInputValue(format(newValue));
131
- setNumberValue(newValue);
132
- validation.commitValidation();
133
- };
134
- let incrementToMax = ()=>{
135
- if (maxValue != null) {
136
- setNumberValue((0, $kNCPO$snapValueToStep)(maxValue, minValue, maxValue, clampStep));
137
- validation.commitValidation();
138
- }
139
- };
140
- let decrementToMin = ()=>{
141
- if (minValue != null) {
142
- setNumberValue(minValue);
143
- validation.commitValidation();
144
- }
145
- };
146
- let canIncrement = (0, $kNCPO$useMemo)(()=>!isDisabled && !isReadOnly && (isNaN(parsedValue) || maxValue === undefined || isNaN(maxValue) || (0, $kNCPO$snapValueToStep)(parsedValue, minValue, maxValue, clampStep) > parsedValue || $de67e98908f0c6ee$var$handleDecimalOperation('+', parsedValue, clampStep) <= maxValue), [
147
- isDisabled,
148
- isReadOnly,
149
- minValue,
150
- maxValue,
151
- clampStep,
152
- parsedValue
153
- ]);
154
- let canDecrement = (0, $kNCPO$useMemo)(()=>!isDisabled && !isReadOnly && (isNaN(parsedValue) || minValue === undefined || isNaN(minValue) || (0, $kNCPO$snapValueToStep)(parsedValue, minValue, maxValue, clampStep) < parsedValue || $de67e98908f0c6ee$var$handleDecimalOperation('-', parsedValue, clampStep) >= minValue), [
155
- isDisabled,
156
- isReadOnly,
157
- minValue,
158
- maxValue,
159
- clampStep,
160
- parsedValue
161
- ]);
162
- let validate = (value)=>numberParser.isValidPartialNumber(value, minValue, maxValue);
163
- return {
164
- ...validation,
165
- validate: validate,
166
- increment: increment,
167
- incrementToMax: incrementToMax,
168
- decrement: decrement,
169
- decrementToMin: decrementToMin,
170
- canIncrement: canIncrement,
171
- canDecrement: canDecrement,
172
- minValue: minValue,
173
- maxValue: maxValue,
174
- numberValue: parsedValue,
175
- defaultNumberValue: isNaN(defaultValue) ? initialValue : defaultValue,
176
- setNumberValue: setNumberValue,
177
- setInputValue: setInputValue,
178
- inputValue: inputValue,
179
- commit: commit
180
- };
181
- }
182
- function $de67e98908f0c6ee$var$handleDecimalOperation(operator, value1, value2) {
183
- let result = operator === '+' ? value1 + value2 : value1 - value2;
184
- // Check if we have decimals
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));
191
- // Transform the decimals to integers based on the precision
192
- value1 = Math.round(value1 * multiplier);
193
- value2 = Math.round(value2 * multiplier);
194
- // Perform the operation on integers values to make sure we don't get a fancy decimal value
195
- result = operator === '+' ? value1 + value2 : value1 - value2;
196
- // Transform the integer result back to decimal
197
- result /= multiplier;
198
- }
199
- return result;
200
- }
201
-
202
-
203
- export {$de67e98908f0c6ee$export$7f629e9dc1ecf37c as useNumberFieldState};
204
- //# sourceMappingURL=useNumberFieldState.module.js.map
@@ -1 +0,0 @@
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 {FormValidationState, useFormValidationState} from '@react-stately/form';\nimport {NumberFieldProps} from '@react-types/numberfield';\nimport {NumberFormatter, NumberParser} from '@internationalized/number';\nimport {useCallback, useMemo, useState} from 'react';\n\nexport interface NumberFieldState extends FormValidationState {\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 default value of the input. */\n defaultNumberValue: 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 /** Sets the number value. */\n setNumberValue(val: number): 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 * @param value - The value to commit. If not provided, the current input value is used.\n */\n commit(value?: string): 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\nexport interface NumberFieldStateOptions 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: NumberFieldStateOptions\n): NumberFieldState {\n let {\n minValue,\n maxValue,\n step,\n formatOptions,\n value,\n defaultValue = NaN,\n onChange,\n locale,\n isDisabled,\n isReadOnly\n } = props;\n\n if (value === null) {\n value = NaN;\n }\n\n if (value !== undefined && !isNaN(value)) {\n if (step !== undefined && !isNaN(step)) {\n value = snapValueToStep(value, minValue, maxValue, step);\n } else {\n value = clamp(value, minValue, maxValue);\n }\n }\n\n if (!isNaN(defaultValue)) {\n if (step !== undefined && !isNaN(step)) {\n defaultValue = snapValueToStep(defaultValue, minValue, maxValue, step);\n } else {\n defaultValue = clamp(defaultValue, minValue, maxValue);\n }\n }\n\n let [numberValue, setNumberValue] = useControlledState<number>(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);\n let [initialValue] = useState(numberValue);\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) || value === null) ? '' : formatter.format(value), [formatter]);\n\n let validation = useFormValidationState({\n ...props,\n value: numberValue\n });\n\n let clampStep = (step !== undefined && !isNaN(step)) ? step : 1;\n if (intlOptions.style === 'percent' && (step === undefined || 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, setPrevValue] = useState(numberValue);\n let [prevLocale, setPrevLocale] = useState(locale);\n let [prevFormatOptions, setPrevFormatOptions] = useState(formatOptions);\n if (!Object.is(numberValue, prevValue) || locale !== prevLocale || formatOptions !== prevFormatOptions) {\n setInputValue(format(numberValue));\n setPrevValue(numberValue);\n setPrevLocale(locale);\n setPrevFormatOptions(formatOptions);\n }\n\n let parsedValue = useMemo(() => numberParser.parse(inputValue), [numberParser, inputValue]);\n let commit = (overrideValue?: string) => {\n let newInputValue = overrideValue === undefined ? inputValue : overrideValue;\n let newParsedValue = parsedValue;\n if (overrideValue !== undefined) {\n newParsedValue = numberParser.parse(newInputValue);\n }\n // Set to empty state if input value is empty\n if (!newInputValue.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(newParsedValue)) {\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 (step === undefined || isNaN(step)) {\n clampedValue = clamp(newParsedValue, minValue, maxValue);\n } else {\n clampedValue = snapValueToStep(newParsedValue, 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 validation.commitValidation();\n };\n\n let safeNextStep = (operation: '+' | '-', minMax: number = 0) => {\n let prev = parsedValue;\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 validation.commitValidation();\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 validation.commitValidation();\n };\n\n let incrementToMax = () => {\n if (maxValue != null) {\n setNumberValue(snapValueToStep(maxValue, minValue, maxValue, clampStep));\n validation.commitValidation();\n }\n };\n\n let decrementToMin = () => {\n if (minValue != null) {\n setNumberValue(minValue);\n validation.commitValidation();\n }\n };\n\n let canIncrement = useMemo(() => (\n !isDisabled &&\n !isReadOnly &&\n (\n isNaN(parsedValue) ||\n (maxValue === undefined || 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 (minValue === undefined || 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 ...validation,\n validate,\n increment,\n incrementToMax,\n decrement,\n decrementToMin,\n canIncrement,\n canDecrement,\n minValue,\n maxValue,\n numberValue: parsedValue,\n defaultNumberValue: isNaN(defaultValue) ? initialValue : defaultValue,\n setNumberValue,\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":"useNumberFieldState.module.js.map"}
@@ -1,317 +0,0 @@
1
- /*
2
- * Copyright 2020 Adobe. All rights reserved.
3
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- * you may not use this file except in compliance with the License. You may obtain a copy
5
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
- *
7
- * Unless required by applicable law or agreed to in writing, software distributed under
8
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
- * OF ANY KIND, either express or implied. See the License for the specific language
10
- * governing permissions and limitations under the License.
11
- */
12
-
13
- import {clamp, snapValueToStep, useControlledState} from '@react-stately/utils';
14
- import {FormValidationState, useFormValidationState} from '@react-stately/form';
15
- import {NumberFieldProps} from '@react-types/numberfield';
16
- import {NumberFormatter, NumberParser} from '@internationalized/number';
17
- import {useCallback, useMemo, useState} from 'react';
18
-
19
- export interface NumberFieldState extends FormValidationState {
20
- /**
21
- * The current text value of the input. Updated as the user types,
22
- * and formatted according to `formatOptions` on blur.
23
- */
24
- inputValue: string,
25
- /**
26
- * The currently parsed number value, or NaN if a valid number could not be parsed.
27
- * Updated based on the `inputValue` as the user types.
28
- */
29
- numberValue: number,
30
- /** The default value of the input. */
31
- defaultNumberValue: number,
32
- /** The minimum value of the number field. */
33
- minValue?: number,
34
- /** The maximum value of the number field. */
35
- maxValue?: number,
36
- /** Whether the current value can be incremented according to the maximum value and step. */
37
- canIncrement: boolean,
38
- /** Whether the current value can be decremented according to the minimum value and step. */
39
- canDecrement: boolean,
40
- /**
41
- * Validates a user input string according to the current locale and format options.
42
- * Values can be partially entered, and may be valid even if they cannot currently be parsed to a number.
43
- * Can be used to implement validation as a user types.
44
- */
45
- validate(value: string): boolean,
46
- /** Sets the current text value of the input. */
47
- setInputValue(val: string): void,
48
- /** Sets the number value. */
49
- setNumberValue(val: number): void,
50
- /**
51
- * Commits the current input value. The value is parsed to a number, clamped according
52
- * to the minimum and maximum values of the field, and snapped to the nearest step value.
53
- * This will fire the `onChange` prop with the new value, and if uncontrolled, update the `numberValue`.
54
- * Typically this is called when the field is blurred.
55
- * @param value - The value to commit. If not provided, the current input value is used.
56
- */
57
- commit(value?: string): void,
58
- /** Increments the current input value to the next step boundary, and fires `onChange`. */
59
- increment(): void,
60
- /** Decrements the current input value to the next step boundary, and fires `onChange`. */
61
- decrement(): void,
62
- /** Sets the current value to the `maxValue` if any, and fires `onChange`. */
63
- incrementToMax(): void,
64
- /** Sets the current value to the `minValue` if any, and fires `onChange`. */
65
- decrementToMin(): void
66
- }
67
-
68
- export interface NumberFieldStateOptions extends NumberFieldProps {
69
- /**
70
- * The locale that should be used for parsing.
71
- * @default 'en-US'
72
- */
73
- locale: string
74
- }
75
-
76
- /**
77
- * Provides state management for a number field component. Number fields allow users to enter a number,
78
- * and increment or decrement the value using stepper buttons.
79
- */
80
- export function useNumberFieldState(
81
- props: NumberFieldStateOptions
82
- ): NumberFieldState {
83
- let {
84
- minValue,
85
- maxValue,
86
- step,
87
- formatOptions,
88
- value,
89
- defaultValue = NaN,
90
- onChange,
91
- locale,
92
- isDisabled,
93
- isReadOnly
94
- } = props;
95
-
96
- if (value === null) {
97
- value = NaN;
98
- }
99
-
100
- if (value !== undefined && !isNaN(value)) {
101
- if (step !== undefined && !isNaN(step)) {
102
- value = snapValueToStep(value, minValue, maxValue, step);
103
- } else {
104
- value = clamp(value, minValue, maxValue);
105
- }
106
- }
107
-
108
- if (!isNaN(defaultValue)) {
109
- if (step !== undefined && !isNaN(step)) {
110
- defaultValue = snapValueToStep(defaultValue, minValue, maxValue, step);
111
- } else {
112
- defaultValue = clamp(defaultValue, minValue, maxValue);
113
- }
114
- }
115
-
116
- let [numberValue, setNumberValue] = useControlledState<number>(value, isNaN(defaultValue) ? NaN : defaultValue, onChange);
117
- let [initialValue] = useState(numberValue);
118
- let [inputValue, setInputValue] = useState(() => isNaN(numberValue) ? '' : new NumberFormatter(locale, formatOptions).format(numberValue));
119
-
120
- let numberParser = useMemo(() => new NumberParser(locale, formatOptions), [locale, formatOptions]);
121
- let numberingSystem = useMemo(() => numberParser.getNumberingSystem(inputValue), [numberParser, inputValue]);
122
- let formatter = useMemo(() => new NumberFormatter(locale, {...formatOptions, numberingSystem}), [locale, formatOptions, numberingSystem]);
123
- let intlOptions = useMemo(() => formatter.resolvedOptions(), [formatter]);
124
- let format = useCallback((value: number) => (isNaN(value) || value === null) ? '' : formatter.format(value), [formatter]);
125
-
126
- let validation = useFormValidationState({
127
- ...props,
128
- value: numberValue
129
- });
130
-
131
- let clampStep = (step !== undefined && !isNaN(step)) ? step : 1;
132
- if (intlOptions.style === 'percent' && (step === undefined || isNaN(step))) {
133
- clampStep = 0.01;
134
- }
135
-
136
- // Update the input value when the number value or format options change. This is done
137
- // in a useEffect so that the controlled behavior is correct and we only update the
138
- // textfield after prop changes.
139
- let [prevValue, setPrevValue] = useState(numberValue);
140
- let [prevLocale, setPrevLocale] = useState(locale);
141
- let [prevFormatOptions, setPrevFormatOptions] = useState(formatOptions);
142
- if (!Object.is(numberValue, prevValue) || locale !== prevLocale || formatOptions !== prevFormatOptions) {
143
- setInputValue(format(numberValue));
144
- setPrevValue(numberValue);
145
- setPrevLocale(locale);
146
- setPrevFormatOptions(formatOptions);
147
- }
148
-
149
- let parsedValue = useMemo(() => numberParser.parse(inputValue), [numberParser, inputValue]);
150
- let commit = (overrideValue?: string) => {
151
- let newInputValue = overrideValue === undefined ? inputValue : overrideValue;
152
- let newParsedValue = parsedValue;
153
- if (overrideValue !== undefined) {
154
- newParsedValue = numberParser.parse(newInputValue);
155
- }
156
- // Set to empty state if input value is empty
157
- if (!newInputValue.length) {
158
- setNumberValue(NaN);
159
- setInputValue(value === undefined ? '' : format(numberValue));
160
- return;
161
- }
162
-
163
- // if it failed to parse, then reset input to formatted version of current number
164
- if (isNaN(newParsedValue)) {
165
- setInputValue(format(numberValue));
166
- return;
167
- }
168
-
169
- // Clamp to min and max, round to the nearest step, and round to specified number of digits
170
- let clampedValue: number;
171
- if (step === undefined || isNaN(step)) {
172
- clampedValue = clamp(newParsedValue, minValue, maxValue);
173
- } else {
174
- clampedValue = snapValueToStep(newParsedValue, minValue, maxValue, step);
175
- }
176
-
177
- clampedValue = numberParser.parse(format(clampedValue));
178
- setNumberValue(clampedValue);
179
-
180
- // in a controlled state, the numberValue won't change, so we won't go back to our old input without help
181
- setInputValue(format(value === undefined ? clampedValue : numberValue));
182
- validation.commitValidation();
183
- };
184
-
185
- let safeNextStep = (operation: '+' | '-', minMax: number = 0) => {
186
- let prev = parsedValue;
187
-
188
- if (isNaN(prev)) {
189
- // if the input is empty, start from the min/max value when incrementing/decrementing,
190
- // or zero if there is no min/max value defined.
191
- let newValue = isNaN(minMax) ? 0 : minMax;
192
- return snapValueToStep(newValue, minValue, maxValue, clampStep);
193
- } else {
194
- // otherwise, first snap the current value to the nearest step. if it moves in the direction
195
- // we're going, use that value, otherwise add the step and snap that value.
196
- let newValue = snapValueToStep(prev, minValue, maxValue, clampStep);
197
- if ((operation === '+' && newValue > prev) || (operation === '-' && newValue < prev)) {
198
- return newValue;
199
- }
200
-
201
- return snapValueToStep(
202
- handleDecimalOperation(operation, prev, clampStep),
203
- minValue,
204
- maxValue,
205
- clampStep
206
- );
207
- }
208
- };
209
-
210
- let increment = () => {
211
- let newValue = safeNextStep('+', minValue);
212
-
213
- // if we've arrived at the same value that was previously in the state, the
214
- // input value should be updated to match
215
- // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
216
- // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
217
- if (newValue === numberValue) {
218
- setInputValue(format(newValue));
219
- }
220
-
221
- setNumberValue(newValue);
222
- validation.commitValidation();
223
- };
224
-
225
- let decrement = () => {
226
- let newValue = safeNextStep('-', maxValue);
227
-
228
- if (newValue === numberValue) {
229
- setInputValue(format(newValue));
230
- }
231
-
232
- setNumberValue(newValue);
233
- validation.commitValidation();
234
- };
235
-
236
- let incrementToMax = () => {
237
- if (maxValue != null) {
238
- setNumberValue(snapValueToStep(maxValue, minValue, maxValue, clampStep));
239
- validation.commitValidation();
240
- }
241
- };
242
-
243
- let decrementToMin = () => {
244
- if (minValue != null) {
245
- setNumberValue(minValue);
246
- validation.commitValidation();
247
- }
248
- };
249
-
250
- let canIncrement = useMemo(() => (
251
- !isDisabled &&
252
- !isReadOnly &&
253
- (
254
- isNaN(parsedValue) ||
255
- (maxValue === undefined || isNaN(maxValue)) ||
256
- snapValueToStep(parsedValue, minValue, maxValue, clampStep) > parsedValue ||
257
- handleDecimalOperation('+', parsedValue, clampStep) <= maxValue
258
- )
259
- ), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);
260
-
261
- let canDecrement = useMemo(() => (
262
- !isDisabled &&
263
- !isReadOnly &&
264
- (
265
- isNaN(parsedValue) ||
266
- (minValue === undefined || isNaN(minValue)) ||
267
- snapValueToStep(parsedValue, minValue, maxValue, clampStep) < parsedValue ||
268
- handleDecimalOperation('-', parsedValue, clampStep) >= minValue
269
- )
270
- ), [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue]);
271
-
272
- let validate = (value: string) => numberParser.isValidPartialNumber(value, minValue, maxValue);
273
-
274
- return {
275
- ...validation,
276
- validate,
277
- increment,
278
- incrementToMax,
279
- decrement,
280
- decrementToMin,
281
- canIncrement,
282
- canDecrement,
283
- minValue,
284
- maxValue,
285
- numberValue: parsedValue,
286
- defaultNumberValue: isNaN(defaultValue) ? initialValue : defaultValue,
287
- setNumberValue,
288
- setInputValue,
289
- inputValue,
290
- commit
291
- };
292
- }
293
-
294
- function handleDecimalOperation(operator: '-' | '+', value1: number, value2: number): number {
295
- let result = operator === '+' ? value1 + value2 : value1 - value2;
296
-
297
- // Check if we have decimals
298
- if (value1 % 1 !== 0 || value2 % 1 !== 0) {
299
- const value1Decimal = value1.toString().split('.');
300
- const value2Decimal = value2.toString().split('.');
301
- const value1DecimalLength = (value1Decimal[1] && value1Decimal[1].length) || 0;
302
- const value2DecimalLength = (value2Decimal[1] && value2Decimal[1].length) || 0;
303
- const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength));
304
-
305
- // Transform the decimals to integers based on the precision
306
- value1 = Math.round(value1 * multiplier);
307
- value2 = Math.round(value2 * multiplier);
308
-
309
- // Perform the operation on integers values to make sure we don't get a fancy decimal value
310
- result = operator === '+' ? value1 + value2 : value1 - value2;
311
-
312
- // Transform the integer result back to decimal
313
- result /= multiplier;
314
- }
315
-
316
- return result;
317
- }