@mantine/core 9.0.0-alpha.2 → 9.0.0-alpha.4
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/cjs/components/NumberInput/NumberInput.cjs +513 -290
- package/cjs/components/NumberInput/NumberInput.cjs.map +1 -1
- package/cjs/components/ScrollArea/ScrollArea.cjs +12 -1
- package/cjs/components/ScrollArea/ScrollArea.cjs.map +1 -1
- package/cjs/components/Tooltip/Tooltip.cjs +3 -1
- package/cjs/components/Tooltip/Tooltip.cjs.map +1 -1
- package/cjs/core/MantineProvider/color-functions/default-variant-colors-resolver/v8-default-variant-colors-resolver.cjs +196 -0
- package/cjs/core/MantineProvider/color-functions/default-variant-colors-resolver/v8-default-variant-colors-resolver.cjs.map +1 -0
- package/cjs/index.cjs +2 -2
- package/esm/components/NumberInput/NumberInput.mjs +514 -291
- package/esm/components/NumberInput/NumberInput.mjs.map +1 -1
- package/esm/components/ScrollArea/ScrollArea.mjs +12 -1
- package/esm/components/ScrollArea/ScrollArea.mjs.map +1 -1
- package/esm/components/Tooltip/Tooltip.mjs +3 -1
- package/esm/components/Tooltip/Tooltip.mjs.map +1 -1
- package/esm/core/MantineProvider/color-functions/default-variant-colors-resolver/v8-default-variant-colors-resolver.mjs +194 -0
- package/esm/core/MantineProvider/color-functions/default-variant-colors-resolver/v8-default-variant-colors-resolver.mjs.map +1 -0
- package/esm/index.mjs +1 -1
- package/lib/components/Input/use-input-props.d.ts +4 -4
- package/lib/components/NumberInput/NumberInput.d.ts +42 -10
- package/lib/components/NumberInput/index.d.ts +3 -3
- package/lib/components/Popover/use-popover.d.ts +1 -1
- package/lib/components/ScrollArea/ScrollArea.d.ts +5 -0
- package/lib/core/MantineProvider/MantineCssVariables/index.d.ts +1 -0
- package/lib/core/MantineProvider/MantineCssVariables/v8-css-variables-resolver.d.ts +2 -0
- package/lib/core/MantineProvider/color-functions/default-variant-colors-resolver/v8-default-variant-colors-resolver.d.ts +2 -0
- package/package.json +2 -2
- package/styles/AppShell.css +11 -1
- package/styles/AppShell.layer.css +11 -1
- package/styles.css +11 -1
- package/styles.layer.css +11 -1
- package/cjs/components/Slider/utils/get-floating-value/get-gloating-value.cjs +0 -9
- package/cjs/components/Slider/utils/get-floating-value/get-gloating-value.cjs.map +0 -1
- package/esm/components/Slider/utils/get-floating-value/get-gloating-value.mjs +0 -7
- package/esm/components/Slider/utils/get-floating-value/get-gloating-value.mjs.map +0 -1
- package/lib/components/Slider/utils/get-floating-value/get-gloating-value.d.ts +0 -1
|
@@ -17,7 +17,7 @@ import '../../core/MantineProvider/MantineThemeProvider/MantineThemeProvider.mjs
|
|
|
17
17
|
import { useProps } from '../../core/MantineProvider/use-props/use-props.mjs';
|
|
18
18
|
import '../../core/MantineProvider/MantineCssVariables/MantineCssVariables.mjs';
|
|
19
19
|
import '../../core/Box/Box.mjs';
|
|
20
|
-
import {
|
|
20
|
+
import { genericFactory } from '../../core/factory/factory.mjs';
|
|
21
21
|
import '../../core/DirectionProvider/DirectionProvider.mjs';
|
|
22
22
|
import { InputBase } from '../InputBase/InputBase.mjs';
|
|
23
23
|
import { UnstyledButton } from '../UnstyledButton/UnstyledButton.mjs';
|
|
@@ -31,12 +31,61 @@ const trailingDecimalSeparatorPattern = /^-?\d+\.$/;
|
|
|
31
31
|
function isNumberString(value) {
|
|
32
32
|
return typeof value === "string" && value !== "" && !Number.isNaN(Number(value));
|
|
33
33
|
}
|
|
34
|
+
function isBigIntValue(value) {
|
|
35
|
+
return typeof value === "bigint";
|
|
36
|
+
}
|
|
34
37
|
function canStep(value) {
|
|
35
38
|
if (typeof value === "number") {
|
|
36
39
|
return value < Number.MAX_SAFE_INTEGER;
|
|
37
40
|
}
|
|
38
41
|
return value === "" || isNumberString(value) && Number(value) < Number.MAX_SAFE_INTEGER;
|
|
39
42
|
}
|
|
43
|
+
function isValidBigIntString(value, allowNegative) {
|
|
44
|
+
if (value === "") {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (value === "-") {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
if (!allowNegative && value.startsWith("-")) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
return /^-?\d+$/.test(value);
|
|
54
|
+
}
|
|
55
|
+
function canStepBigInt(value, allowNegative) {
|
|
56
|
+
if (typeof value === "bigint") {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return value === "" || isValidBigIntString(value, allowNegative);
|
|
60
|
+
}
|
|
61
|
+
function parseBigIntFromString(value) {
|
|
62
|
+
if (!/^-?\d+$/.test(value)) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
return BigInt(value);
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function toBigIntOrUndefined(value) {
|
|
72
|
+
if (typeof value === "bigint") {
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
if (typeof value === "number" && Number.isFinite(value) && Number.isInteger(value)) {
|
|
76
|
+
return BigInt(value);
|
|
77
|
+
}
|
|
78
|
+
return void 0;
|
|
79
|
+
}
|
|
80
|
+
function clampBigInt(value, min, max) {
|
|
81
|
+
if (min !== void 0 && value < min) {
|
|
82
|
+
return min;
|
|
83
|
+
}
|
|
84
|
+
if (max !== void 0 && value > max) {
|
|
85
|
+
return max;
|
|
86
|
+
}
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
40
89
|
function getTotalDigits(inputValue) {
|
|
41
90
|
return inputValue.toString().replace(".", "").length;
|
|
42
91
|
}
|
|
@@ -85,306 +134,480 @@ function clampAndSanitizeInput(sanitizedValue, max, min) {
|
|
|
85
134
|
}
|
|
86
135
|
return clamped;
|
|
87
136
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
rightSection,
|
|
105
|
-
isAllowed,
|
|
106
|
-
clampBehavior,
|
|
107
|
-
onBlur,
|
|
108
|
-
allowDecimal,
|
|
109
|
-
decimalScale,
|
|
110
|
-
onKeyDown,
|
|
111
|
-
onKeyDownCapture,
|
|
112
|
-
handlersRef,
|
|
113
|
-
startValue,
|
|
114
|
-
disabled,
|
|
115
|
-
rightSectionPointerEvents,
|
|
116
|
-
allowNegative,
|
|
117
|
-
readOnly,
|
|
118
|
-
size,
|
|
119
|
-
rightSectionWidth,
|
|
120
|
-
stepHoldInterval,
|
|
121
|
-
stepHoldDelay,
|
|
122
|
-
allowLeadingZeros,
|
|
123
|
-
withKeyboardEvents,
|
|
124
|
-
trimLeadingZeroesOnBlur,
|
|
125
|
-
allowedDecimalSeparators,
|
|
126
|
-
selectAllOnFocus,
|
|
127
|
-
onMinReached,
|
|
128
|
-
onMaxReached,
|
|
129
|
-
onFocus,
|
|
130
|
-
attributes,
|
|
131
|
-
ref,
|
|
132
|
-
...others
|
|
133
|
-
} = props;
|
|
134
|
-
const getStyles = useStyles({
|
|
135
|
-
name: "NumberInput",
|
|
136
|
-
classes,
|
|
137
|
-
props,
|
|
138
|
-
classNames,
|
|
139
|
-
styles,
|
|
140
|
-
unstyled,
|
|
141
|
-
attributes,
|
|
142
|
-
vars,
|
|
143
|
-
varsResolver
|
|
144
|
-
});
|
|
145
|
-
const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi({
|
|
146
|
-
classNames,
|
|
147
|
-
styles,
|
|
148
|
-
props
|
|
149
|
-
});
|
|
150
|
-
const [_value, setValue] = useUncontrolled({
|
|
151
|
-
value,
|
|
152
|
-
defaultValue,
|
|
153
|
-
finalValue: "",
|
|
154
|
-
onChange
|
|
155
|
-
});
|
|
156
|
-
const shouldUseStepInterval = stepHoldDelay !== void 0 && stepHoldInterval !== void 0;
|
|
157
|
-
const inputRef = useRef(null);
|
|
158
|
-
const onStepTimeoutRef = useRef(null);
|
|
159
|
-
const stepCountRef = useRef(0);
|
|
160
|
-
const handleValueChange = (payload, event) => {
|
|
161
|
-
if (event.source === "event") {
|
|
162
|
-
setValue(
|
|
163
|
-
isValidNumber(payload.floatValue, payload.value) && !leadingDecimalZeroPattern.test(payload.value) && !(allowLeadingZeros ? leadingZerosPattern.test(payload.value) : false) && !trailingZerosPattern.test(payload.value) && !trailingDecimalSeparatorPattern.test(payload.value) ? payload.floatValue : payload.value
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
onValueChange?.(payload, event);
|
|
167
|
-
};
|
|
168
|
-
const getDecimalPlaces = (inputValue) => {
|
|
169
|
-
const match = String(inputValue).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
|
|
170
|
-
if (!match) {
|
|
171
|
-
return 0;
|
|
172
|
-
}
|
|
173
|
-
return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
|
|
174
|
-
};
|
|
175
|
-
const adjustCursor = (position) => {
|
|
176
|
-
if (inputRef.current && typeof position !== "undefined") {
|
|
177
|
-
inputRef.current.setSelectionRange(position, position);
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
const incrementRef = useRef(noop);
|
|
181
|
-
incrementRef.current = () => {
|
|
182
|
-
if (!canStep(_value)) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
let val;
|
|
186
|
-
const currentValuePrecision = getDecimalPlaces(_value);
|
|
187
|
-
const stepPrecision = getDecimalPlaces(step);
|
|
188
|
-
const maxPrecision = Math.max(currentValuePrecision, stepPrecision);
|
|
189
|
-
const factor = 10 ** maxPrecision;
|
|
190
|
-
if (!isNumberString(_value) && (typeof _value !== "number" || Number.isNaN(_value))) {
|
|
191
|
-
val = clamp(startValue, min, max);
|
|
192
|
-
} else if (max !== void 0) {
|
|
193
|
-
const incrementedValue = (Math.round(Number(_value) * factor) + Math.round(step * factor)) / factor;
|
|
194
|
-
if (incrementedValue > max) {
|
|
195
|
-
onMaxReached?.();
|
|
196
|
-
}
|
|
197
|
-
val = incrementedValue <= max ? incrementedValue : max;
|
|
198
|
-
} else {
|
|
199
|
-
val = (Math.round(Number(_value) * factor) + Math.round(step * factor)) / factor;
|
|
200
|
-
}
|
|
201
|
-
const formattedValue = val.toFixed(maxPrecision);
|
|
202
|
-
setValue(parseFloat(formattedValue));
|
|
203
|
-
onValueChange?.(
|
|
204
|
-
{ floatValue: parseFloat(formattedValue), formattedValue, value: formattedValue },
|
|
205
|
-
{ source: "increment" }
|
|
137
|
+
function clampAndSanitizeBigIntInput(sanitizedValue, options) {
|
|
138
|
+
if (sanitizedValue === "" || sanitizedValue === "-") {
|
|
139
|
+
return sanitizedValue;
|
|
140
|
+
}
|
|
141
|
+
const parsed = parseBigIntFromString(sanitizedValue);
|
|
142
|
+
if (parsed === null) {
|
|
143
|
+
return sanitizedValue;
|
|
144
|
+
}
|
|
145
|
+
return options.clampBehavior === "blur" ? clampBigInt(parsed, options.min, options.max) : parsed;
|
|
146
|
+
}
|
|
147
|
+
const NumberInput = genericFactory(
|
|
148
|
+
(_props) => {
|
|
149
|
+
const props = useProps(
|
|
150
|
+
"NumberInput",
|
|
151
|
+
defaultProps,
|
|
152
|
+
_props
|
|
206
153
|
);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
154
|
+
const {
|
|
155
|
+
className,
|
|
156
|
+
classNames,
|
|
157
|
+
styles,
|
|
158
|
+
unstyled,
|
|
159
|
+
vars,
|
|
160
|
+
onChange,
|
|
161
|
+
onValueChange,
|
|
162
|
+
value,
|
|
163
|
+
defaultValue,
|
|
164
|
+
max,
|
|
165
|
+
min,
|
|
166
|
+
step,
|
|
167
|
+
hideControls,
|
|
168
|
+
rightSection,
|
|
169
|
+
isAllowed,
|
|
170
|
+
clampBehavior,
|
|
171
|
+
onBlur,
|
|
172
|
+
allowDecimal,
|
|
173
|
+
decimalScale,
|
|
174
|
+
onKeyDown,
|
|
175
|
+
onKeyDownCapture,
|
|
176
|
+
handlersRef,
|
|
177
|
+
startValue,
|
|
178
|
+
disabled,
|
|
179
|
+
rightSectionPointerEvents,
|
|
180
|
+
allowNegative,
|
|
181
|
+
readOnly,
|
|
182
|
+
size,
|
|
183
|
+
rightSectionWidth,
|
|
184
|
+
stepHoldInterval,
|
|
185
|
+
stepHoldDelay,
|
|
186
|
+
allowLeadingZeros,
|
|
187
|
+
withKeyboardEvents,
|
|
188
|
+
trimLeadingZeroesOnBlur,
|
|
189
|
+
allowedDecimalSeparators,
|
|
190
|
+
selectAllOnFocus,
|
|
191
|
+
onMinReached,
|
|
192
|
+
onMaxReached,
|
|
193
|
+
onFocus,
|
|
194
|
+
attributes,
|
|
195
|
+
ref,
|
|
196
|
+
...others
|
|
197
|
+
} = props;
|
|
198
|
+
const allowNegativeResolved = allowNegative ?? true;
|
|
199
|
+
const allowLeadingZerosResolved = allowLeadingZeros ?? true;
|
|
200
|
+
const getStyles = useStyles({
|
|
201
|
+
name: "NumberInput",
|
|
202
|
+
classes,
|
|
203
|
+
props,
|
|
204
|
+
classNames,
|
|
205
|
+
styles,
|
|
206
|
+
unstyled,
|
|
207
|
+
attributes,
|
|
208
|
+
vars,
|
|
209
|
+
varsResolver
|
|
210
|
+
});
|
|
211
|
+
const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi({
|
|
212
|
+
classNames,
|
|
213
|
+
styles,
|
|
214
|
+
props
|
|
215
|
+
});
|
|
216
|
+
const valueModeRef = useRef(
|
|
217
|
+
isBigIntValue(value) || isBigIntValue(defaultValue) ? "bigint" : "number"
|
|
234
218
|
);
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if (readOnly || !withKeyboardEvents) {
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
if (event.key === "ArrowUp") {
|
|
243
|
-
event.preventDefault();
|
|
244
|
-
incrementRef.current?.();
|
|
219
|
+
if (isBigIntValue(value)) {
|
|
220
|
+
valueModeRef.current = "bigint";
|
|
221
|
+
} else if (typeof value === "number") {
|
|
222
|
+
valueModeRef.current = "number";
|
|
245
223
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
224
|
+
const isBigIntMode = valueModeRef.current === "bigint";
|
|
225
|
+
const [_value, setValue] = useUncontrolled({
|
|
226
|
+
value,
|
|
227
|
+
defaultValue,
|
|
228
|
+
finalValue: "",
|
|
229
|
+
onChange
|
|
230
|
+
});
|
|
231
|
+
const shouldUseStepInterval = stepHoldDelay !== void 0 && stepHoldInterval !== void 0;
|
|
232
|
+
const inputRef = useRef(null);
|
|
233
|
+
const onStepTimeoutRef = useRef(null);
|
|
234
|
+
const stepCountRef = useRef(0);
|
|
235
|
+
const minNumber = typeof min === "number" ? min : void 0;
|
|
236
|
+
const maxNumber = typeof max === "number" ? max : void 0;
|
|
237
|
+
const stepNumber = typeof step === "number" ? step : defaultProps.step;
|
|
238
|
+
const startValueNumber = typeof startValue === "number" ? startValue : defaultProps.startValue;
|
|
239
|
+
const minBigInt = toBigIntOrUndefined(min);
|
|
240
|
+
const maxBigInt = toBigIntOrUndefined(max);
|
|
241
|
+
const stepBigInt = toBigIntOrUndefined(step) ?? BigInt(1);
|
|
242
|
+
const startValueBigInt = toBigIntOrUndefined(startValue) ?? BigInt(0);
|
|
243
|
+
const parseBigIntOrString = (inputValue) => {
|
|
244
|
+
if (!isValidBigIntString(inputValue, allowNegativeResolved) || allowLeadingZerosResolved && leadingZerosPattern.test(inputValue)) {
|
|
245
|
+
return inputValue;
|
|
246
|
+
}
|
|
247
|
+
const parsed = parseBigIntFromString(inputValue);
|
|
248
|
+
return parsed ?? inputValue;
|
|
249
|
+
};
|
|
250
|
+
const getBigIntFloatValue = (inputValue) => {
|
|
251
|
+
const numericValue = Number(inputValue);
|
|
252
|
+
return Number.isSafeInteger(numericValue) ? numericValue : void 0;
|
|
253
|
+
};
|
|
254
|
+
const handleValueChange = (payload, event) => {
|
|
255
|
+
if (event.source === "event") {
|
|
256
|
+
if (isBigIntMode) {
|
|
257
|
+
setValue(parseBigIntOrString(payload.value));
|
|
258
|
+
} else {
|
|
259
|
+
setValue(
|
|
260
|
+
isValidNumber(payload.floatValue, payload.value) && !leadingDecimalZeroPattern.test(payload.value) && !(allowLeadingZerosResolved ? leadingZerosPattern.test(payload.value) : false) && !trailingZerosPattern.test(payload.value) && !trailingDecimalSeparatorPattern.test(payload.value) ? payload.floatValue : payload.value
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
onValueChange?.(payload, event);
|
|
265
|
+
};
|
|
266
|
+
const getDecimalPlaces = (inputValue) => {
|
|
267
|
+
const match = String(inputValue).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
|
|
268
|
+
if (!match) {
|
|
269
|
+
return 0;
|
|
270
|
+
}
|
|
271
|
+
return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
|
|
272
|
+
};
|
|
273
|
+
const adjustCursor = (position) => {
|
|
274
|
+
if (inputRef.current && typeof position !== "undefined") {
|
|
275
|
+
inputRef.current.setSelectionRange(position, position);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
const incrementRef = useRef(noop);
|
|
279
|
+
incrementRef.current = () => {
|
|
280
|
+
if (isBigIntMode) {
|
|
281
|
+
if (!canStepBigInt(_value, allowNegativeResolved)) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
let val2;
|
|
285
|
+
const currentValue = _value;
|
|
286
|
+
if (typeof currentValue === "bigint") {
|
|
287
|
+
const incrementedValue = currentValue + stepBigInt;
|
|
288
|
+
if (maxBigInt !== void 0 && incrementedValue > maxBigInt) {
|
|
289
|
+
onMaxReached?.();
|
|
290
|
+
}
|
|
291
|
+
val2 = maxBigInt !== void 0 && incrementedValue > maxBigInt ? maxBigInt : incrementedValue;
|
|
292
|
+
} else if (typeof currentValue === "string" && currentValue !== "") {
|
|
293
|
+
const parsed = parseBigIntFromString(currentValue);
|
|
294
|
+
if (parsed === null) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
const incrementedValue = parsed + stepBigInt;
|
|
298
|
+
if (maxBigInt !== void 0 && incrementedValue > maxBigInt) {
|
|
299
|
+
onMaxReached?.();
|
|
300
|
+
}
|
|
301
|
+
val2 = maxBigInt !== void 0 && incrementedValue > maxBigInt ? maxBigInt : incrementedValue;
|
|
302
|
+
} else {
|
|
303
|
+
val2 = clampBigInt(startValueBigInt, minBigInt, maxBigInt);
|
|
304
|
+
}
|
|
305
|
+
const formattedValue2 = val2.toString();
|
|
306
|
+
setValue(val2);
|
|
307
|
+
onValueChange?.(
|
|
308
|
+
{ floatValue: getBigIntFloatValue(val2), formattedValue: formattedValue2, value: formattedValue2 },
|
|
309
|
+
{ source: "increment" }
|
|
310
|
+
);
|
|
311
|
+
setTimeout(() => adjustCursor(inputRef.current?.value.length), 0);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
if (!canStep(_value)) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
let val;
|
|
318
|
+
const currentValuePrecision = getDecimalPlaces(_value);
|
|
319
|
+
const stepPrecision = getDecimalPlaces(stepNumber);
|
|
320
|
+
const maxPrecision = Math.max(currentValuePrecision, stepPrecision);
|
|
321
|
+
const factor = 10 ** maxPrecision;
|
|
322
|
+
if (!isNumberString(_value) && (typeof _value !== "number" || Number.isNaN(_value))) {
|
|
323
|
+
val = clamp(startValueNumber, minNumber, maxNumber);
|
|
324
|
+
} else if (maxNumber !== void 0) {
|
|
325
|
+
const incrementedValue = (Math.round(Number(_value) * factor) + Math.round(stepNumber * factor)) / factor;
|
|
326
|
+
if (incrementedValue > maxNumber) {
|
|
327
|
+
onMaxReached?.();
|
|
328
|
+
}
|
|
329
|
+
val = incrementedValue <= maxNumber ? incrementedValue : maxNumber;
|
|
330
|
+
} else {
|
|
331
|
+
val = (Math.round(Number(_value) * factor) + Math.round(stepNumber * factor)) / factor;
|
|
332
|
+
}
|
|
333
|
+
const formattedValue = val.toFixed(maxPrecision);
|
|
334
|
+
setValue(parseFloat(formattedValue));
|
|
335
|
+
onValueChange?.(
|
|
336
|
+
{ floatValue: parseFloat(formattedValue), formattedValue, value: formattedValue },
|
|
337
|
+
{ source: "increment" }
|
|
338
|
+
);
|
|
339
|
+
setTimeout(() => adjustCursor(inputRef.current?.value.length), 0);
|
|
340
|
+
};
|
|
341
|
+
const decrementRef = useRef(noop);
|
|
342
|
+
decrementRef.current = () => {
|
|
343
|
+
if (isBigIntMode) {
|
|
344
|
+
if (!canStepBigInt(_value, allowNegativeResolved)) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
let val2;
|
|
348
|
+
const minValue2 = minBigInt !== void 0 ? minBigInt : !allowNegativeResolved ? BigInt(0) : void 0;
|
|
349
|
+
const currentValue = _value;
|
|
350
|
+
if (typeof currentValue === "bigint") {
|
|
351
|
+
const decrementedValue = currentValue - stepBigInt;
|
|
352
|
+
if (minValue2 !== void 0 && decrementedValue < minValue2) {
|
|
353
|
+
onMinReached?.();
|
|
354
|
+
}
|
|
355
|
+
val2 = minValue2 !== void 0 && decrementedValue < minValue2 ? minValue2 : decrementedValue;
|
|
356
|
+
} else if (typeof currentValue === "string" && currentValue !== "") {
|
|
357
|
+
const parsed = parseBigIntFromString(currentValue);
|
|
358
|
+
if (parsed === null) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const decrementedValue = parsed - stepBigInt;
|
|
362
|
+
if (minValue2 !== void 0 && decrementedValue < minValue2) {
|
|
363
|
+
onMinReached?.();
|
|
364
|
+
}
|
|
365
|
+
val2 = minValue2 !== void 0 && decrementedValue < minValue2 ? minValue2 : decrementedValue;
|
|
366
|
+
} else {
|
|
367
|
+
val2 = clampBigInt(startValueBigInt, minValue2, maxBigInt);
|
|
368
|
+
}
|
|
369
|
+
const formattedValue2 = val2.toString();
|
|
370
|
+
setValue(val2);
|
|
371
|
+
onValueChange?.(
|
|
372
|
+
{ floatValue: getBigIntFloatValue(val2), formattedValue: formattedValue2, value: formattedValue2 },
|
|
373
|
+
{ source: "decrement" }
|
|
374
|
+
);
|
|
375
|
+
setTimeout(() => adjustCursor(inputRef.current?.value.length), 0);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
if (!canStep(_value)) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
let val;
|
|
382
|
+
const minValue = minNumber !== void 0 ? minNumber : !allowNegativeResolved ? 0 : Number.MIN_SAFE_INTEGER;
|
|
383
|
+
const currentValuePrecision = getDecimalPlaces(_value);
|
|
384
|
+
const stepPrecision = getDecimalPlaces(stepNumber);
|
|
385
|
+
const maxPrecision = Math.max(currentValuePrecision, stepPrecision);
|
|
386
|
+
const factor = 10 ** maxPrecision;
|
|
387
|
+
if (!isNumberString(_value) && typeof _value !== "number" || Number.isNaN(_value)) {
|
|
388
|
+
val = clamp(startValueNumber, minValue, maxNumber);
|
|
389
|
+
} else {
|
|
390
|
+
const decrementedValue = (Math.round(Number(_value) * factor) - Math.round(stepNumber * factor)) / factor;
|
|
391
|
+
if (minValue !== void 0 && decrementedValue < minValue) {
|
|
392
|
+
onMinReached?.();
|
|
393
|
+
}
|
|
394
|
+
val = minValue !== void 0 && decrementedValue < minValue ? minValue : decrementedValue;
|
|
395
|
+
}
|
|
396
|
+
const formattedValue = val.toFixed(maxPrecision);
|
|
397
|
+
setValue(parseFloat(formattedValue));
|
|
398
|
+
onValueChange?.(
|
|
399
|
+
{ floatValue: parseFloat(formattedValue), formattedValue, value: formattedValue },
|
|
400
|
+
{ source: "decrement" }
|
|
401
|
+
);
|
|
402
|
+
setTimeout(() => adjustCursor(inputRef.current?.value.length), 0);
|
|
403
|
+
};
|
|
404
|
+
const handlePaste = (event) => {
|
|
405
|
+
const pastedText = event.clipboardData.getData("text");
|
|
406
|
+
const _decimalSeparator = others.decimalSeparator || ".";
|
|
407
|
+
const separatorsToReplace = (allowedDecimalSeparators || [".", ","]).filter(
|
|
408
|
+
(s) => s !== _decimalSeparator
|
|
409
|
+
);
|
|
410
|
+
if (separatorsToReplace.some((s) => pastedText.includes(s))) {
|
|
256
411
|
event.preventDefault();
|
|
257
|
-
|
|
412
|
+
let modifiedText = pastedText;
|
|
413
|
+
separatorsToReplace.forEach((s) => {
|
|
414
|
+
modifiedText = modifiedText.split(s).join(_decimalSeparator);
|
|
415
|
+
});
|
|
416
|
+
const input = inputRef.current;
|
|
417
|
+
if (input) {
|
|
418
|
+
const start = input.selectionStart ?? 0;
|
|
419
|
+
const end = input.selectionEnd ?? 0;
|
|
420
|
+
const currentValue = input.value;
|
|
421
|
+
const newValue = currentValue.substring(0, start) + modifiedText + currentValue.substring(end);
|
|
422
|
+
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
|
|
423
|
+
window.HTMLInputElement.prototype,
|
|
424
|
+
"value"
|
|
425
|
+
)?.set;
|
|
426
|
+
nativeInputValueSetter?.call(input, newValue);
|
|
427
|
+
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
428
|
+
const cursorPos = start + modifiedText.length;
|
|
429
|
+
setTimeout(() => adjustCursor(cursorPos), 0);
|
|
430
|
+
}
|
|
258
431
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
onFocus?.(event);
|
|
266
|
-
};
|
|
267
|
-
const handleBlur = (event) => {
|
|
268
|
-
let sanitizedValue = _value;
|
|
269
|
-
if (clampBehavior === "blur" && typeof sanitizedValue === "number") {
|
|
270
|
-
sanitizedValue = clamp(sanitizedValue, min, max);
|
|
271
|
-
}
|
|
272
|
-
if (trimLeadingZeroesOnBlur && typeof sanitizedValue === "string" && getDecimalPlaces(sanitizedValue) < 15) {
|
|
273
|
-
sanitizedValue = clampAndSanitizeInput(sanitizedValue, max, min);
|
|
274
|
-
}
|
|
275
|
-
if (_value !== sanitizedValue) {
|
|
276
|
-
setValue(sanitizedValue);
|
|
277
|
-
}
|
|
278
|
-
onBlur?.(event);
|
|
279
|
-
};
|
|
280
|
-
assignRef(handlersRef, { increment: incrementRef.current, decrement: decrementRef.current });
|
|
281
|
-
const onStepHandleChange = (isIncrement) => {
|
|
282
|
-
if (isIncrement) {
|
|
283
|
-
incrementRef.current?.();
|
|
284
|
-
} else {
|
|
285
|
-
decrementRef.current?.();
|
|
286
|
-
}
|
|
287
|
-
stepCountRef.current += 1;
|
|
288
|
-
};
|
|
289
|
-
const onStepLoop = (isIncrement) => {
|
|
290
|
-
onStepHandleChange(isIncrement);
|
|
291
|
-
if (shouldUseStepInterval) {
|
|
292
|
-
const interval = typeof stepHoldInterval === "number" ? stepHoldInterval : stepHoldInterval(stepCountRef.current);
|
|
293
|
-
onStepTimeoutRef.current = window.setTimeout(() => onStepLoop(isIncrement), interval);
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
const onStep = (event, isIncrement) => {
|
|
297
|
-
event.preventDefault();
|
|
298
|
-
inputRef.current?.focus();
|
|
299
|
-
onStepHandleChange(isIncrement);
|
|
300
|
-
if (shouldUseStepInterval) {
|
|
301
|
-
onStepTimeoutRef.current = window.setTimeout(() => onStepLoop(isIncrement), stepHoldDelay);
|
|
302
|
-
}
|
|
303
|
-
};
|
|
304
|
-
const onStepDone = () => {
|
|
305
|
-
if (onStepTimeoutRef.current) {
|
|
306
|
-
window.clearTimeout(onStepTimeoutRef.current);
|
|
307
|
-
}
|
|
308
|
-
onStepTimeoutRef.current = null;
|
|
309
|
-
stepCountRef.current = 0;
|
|
310
|
-
};
|
|
311
|
-
const controls = /* @__PURE__ */ jsxs("div", { ...getStyles("controls"), children: [
|
|
312
|
-
/* @__PURE__ */ jsx(
|
|
313
|
-
UnstyledButton,
|
|
314
|
-
{
|
|
315
|
-
...getStyles("control"),
|
|
316
|
-
tabIndex: -1,
|
|
317
|
-
"aria-hidden": true,
|
|
318
|
-
disabled: disabled || typeof _value === "number" && max !== void 0 && _value >= max,
|
|
319
|
-
mod: { direction: "up" },
|
|
320
|
-
onMouseDown: (event) => event.preventDefault(),
|
|
321
|
-
onPointerDown: (event) => {
|
|
322
|
-
onStep(event, true);
|
|
323
|
-
},
|
|
324
|
-
onPointerUp: onStepDone,
|
|
325
|
-
onPointerLeave: onStepDone,
|
|
326
|
-
children: /* @__PURE__ */ jsx(NumberInputChevron, { direction: "up" })
|
|
432
|
+
others.onPaste?.(event);
|
|
433
|
+
};
|
|
434
|
+
const handleKeyDown = (event) => {
|
|
435
|
+
onKeyDown?.(event);
|
|
436
|
+
if (readOnly || !withKeyboardEvents) {
|
|
437
|
+
return;
|
|
327
438
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
{
|
|
332
|
-
...getStyles("control"),
|
|
333
|
-
tabIndex: -1,
|
|
334
|
-
"aria-hidden": true,
|
|
335
|
-
disabled: disabled || typeof _value === "number" && min !== void 0 && _value <= min,
|
|
336
|
-
mod: { direction: "down" },
|
|
337
|
-
onMouseDown: (event) => event.preventDefault(),
|
|
338
|
-
onPointerDown: (event) => {
|
|
339
|
-
onStep(event, false);
|
|
340
|
-
},
|
|
341
|
-
onPointerUp: onStepDone,
|
|
342
|
-
onPointerLeave: onStepDone,
|
|
343
|
-
children: /* @__PURE__ */ jsx(NumberInputChevron, { direction: "down" })
|
|
439
|
+
if (event.key === "ArrowUp") {
|
|
440
|
+
event.preventDefault();
|
|
441
|
+
incrementRef.current?.();
|
|
344
442
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
443
|
+
if (event.key === "ArrowDown") {
|
|
444
|
+
event.preventDefault();
|
|
445
|
+
decrementRef.current?.();
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
const handleKeyDownCapture = (event) => {
|
|
449
|
+
onKeyDownCapture?.(event);
|
|
450
|
+
if (event.key === "Backspace") {
|
|
451
|
+
const input = inputRef.current;
|
|
452
|
+
if (input && input.selectionStart === 0 && input.selectionStart === input.selectionEnd) {
|
|
453
|
+
event.preventDefault();
|
|
454
|
+
window.setTimeout(() => adjustCursor(0), 0);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
const handleFocus = (event) => {
|
|
459
|
+
if (selectAllOnFocus) {
|
|
460
|
+
setTimeout(() => event.currentTarget.select(), 0);
|
|
461
|
+
}
|
|
462
|
+
onFocus?.(event);
|
|
463
|
+
};
|
|
464
|
+
const handleBlur = (event) => {
|
|
465
|
+
let sanitizedValue = _value;
|
|
466
|
+
if (isBigIntMode) {
|
|
467
|
+
if (clampBehavior === "blur" && typeof sanitizedValue === "bigint") {
|
|
468
|
+
sanitizedValue = clampBigInt(sanitizedValue, minBigInt, maxBigInt);
|
|
469
|
+
}
|
|
470
|
+
if (trimLeadingZeroesOnBlur && typeof sanitizedValue === "string") {
|
|
471
|
+
sanitizedValue = clampAndSanitizeBigIntInput(sanitizedValue, {
|
|
472
|
+
min: minBigInt,
|
|
473
|
+
max: maxBigInt,
|
|
474
|
+
clampBehavior
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
} else {
|
|
478
|
+
if (clampBehavior === "blur" && typeof sanitizedValue === "number") {
|
|
479
|
+
sanitizedValue = clamp(sanitizedValue, minNumber, maxNumber);
|
|
480
|
+
}
|
|
481
|
+
if (trimLeadingZeroesOnBlur && typeof sanitizedValue === "string" && getDecimalPlaces(sanitizedValue) < 15) {
|
|
482
|
+
sanitizedValue = clampAndSanitizeInput(sanitizedValue, maxNumber, minNumber);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
if (_value !== sanitizedValue) {
|
|
486
|
+
setValue(sanitizedValue);
|
|
487
|
+
}
|
|
488
|
+
onBlur?.(event);
|
|
489
|
+
};
|
|
490
|
+
assignRef(handlersRef, { increment: incrementRef.current, decrement: decrementRef.current });
|
|
491
|
+
const onStepHandleChange = (isIncrement) => {
|
|
492
|
+
if (isIncrement) {
|
|
493
|
+
incrementRef.current?.();
|
|
494
|
+
} else {
|
|
495
|
+
decrementRef.current?.();
|
|
496
|
+
}
|
|
497
|
+
stepCountRef.current += 1;
|
|
498
|
+
};
|
|
499
|
+
const onStepLoop = (isIncrement) => {
|
|
500
|
+
onStepHandleChange(isIncrement);
|
|
501
|
+
if (shouldUseStepInterval) {
|
|
502
|
+
const interval = typeof stepHoldInterval === "number" ? stepHoldInterval : stepHoldInterval(stepCountRef.current);
|
|
503
|
+
onStepTimeoutRef.current = window.setTimeout(() => onStepLoop(isIncrement), interval);
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
const onStep = (event, isIncrement) => {
|
|
507
|
+
event.preventDefault();
|
|
508
|
+
inputRef.current?.focus();
|
|
509
|
+
onStepHandleChange(isIncrement);
|
|
510
|
+
if (shouldUseStepInterval) {
|
|
511
|
+
onStepTimeoutRef.current = window.setTimeout(() => onStepLoop(isIncrement), stepHoldDelay);
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
const onStepDone = () => {
|
|
515
|
+
if (onStepTimeoutRef.current) {
|
|
516
|
+
window.clearTimeout(onStepTimeoutRef.current);
|
|
517
|
+
}
|
|
518
|
+
onStepTimeoutRef.current = null;
|
|
519
|
+
stepCountRef.current = 0;
|
|
520
|
+
};
|
|
521
|
+
const controls = /* @__PURE__ */ jsxs("div", { ...getStyles("controls"), children: [
|
|
522
|
+
/* @__PURE__ */ jsx(
|
|
523
|
+
UnstyledButton,
|
|
524
|
+
{
|
|
525
|
+
...getStyles("control"),
|
|
526
|
+
tabIndex: -1,
|
|
527
|
+
"aria-hidden": true,
|
|
528
|
+
disabled: disabled || typeof _value === "number" && maxNumber !== void 0 && _value >= maxNumber || typeof _value === "bigint" && maxBigInt !== void 0 && _value >= maxBigInt,
|
|
529
|
+
mod: { direction: "up" },
|
|
530
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
531
|
+
onPointerDown: (event) => {
|
|
532
|
+
onStep(event, true);
|
|
533
|
+
},
|
|
534
|
+
onPointerUp: onStepDone,
|
|
535
|
+
onPointerLeave: onStepDone,
|
|
536
|
+
children: /* @__PURE__ */ jsx(NumberInputChevron, { direction: "up" })
|
|
537
|
+
}
|
|
538
|
+
),
|
|
539
|
+
/* @__PURE__ */ jsx(
|
|
540
|
+
UnstyledButton,
|
|
541
|
+
{
|
|
542
|
+
...getStyles("control"),
|
|
543
|
+
tabIndex: -1,
|
|
544
|
+
"aria-hidden": true,
|
|
545
|
+
disabled: disabled || typeof _value === "number" && minNumber !== void 0 && _value <= minNumber || typeof _value === "bigint" && minBigInt !== void 0 && _value <= minBigInt,
|
|
546
|
+
mod: { direction: "down" },
|
|
547
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
548
|
+
onPointerDown: (event) => {
|
|
549
|
+
onStep(event, false);
|
|
550
|
+
},
|
|
551
|
+
onPointerUp: onStepDone,
|
|
552
|
+
onPointerLeave: onStepDone,
|
|
553
|
+
children: /* @__PURE__ */ jsx(NumberInputChevron, { direction: "down" })
|
|
554
|
+
}
|
|
555
|
+
)
|
|
556
|
+
] });
|
|
557
|
+
return /* @__PURE__ */ jsx(
|
|
558
|
+
InputBase,
|
|
559
|
+
{
|
|
560
|
+
component: NumericFormat,
|
|
561
|
+
allowNegative,
|
|
562
|
+
className: cx(classes.root, className),
|
|
563
|
+
size,
|
|
564
|
+
...others,
|
|
565
|
+
inputMode: isBigIntMode ? "numeric" : "decimal",
|
|
566
|
+
readOnly,
|
|
567
|
+
disabled,
|
|
568
|
+
value: typeof _value === "bigint" ? _value.toString() : _value,
|
|
569
|
+
getInputRef: useMergedRef(ref, inputRef),
|
|
570
|
+
onValueChange: handleValueChange,
|
|
571
|
+
rightSection: hideControls || readOnly || !(isBigIntMode ? canStepBigInt(_value, allowNegativeResolved) : canStep(_value)) ? rightSection : rightSection || controls,
|
|
572
|
+
classNames: resolvedClassNames,
|
|
573
|
+
styles: resolvedStyles,
|
|
574
|
+
unstyled,
|
|
575
|
+
__staticSelector: "NumberInput",
|
|
576
|
+
decimalScale: isBigIntMode ? 0 : allowDecimal ? decimalScale : 0,
|
|
577
|
+
onPaste: handlePaste,
|
|
578
|
+
onFocus: handleFocus,
|
|
579
|
+
onKeyDown: handleKeyDown,
|
|
580
|
+
onKeyDownCapture: handleKeyDownCapture,
|
|
581
|
+
rightSectionPointerEvents: rightSectionPointerEvents ?? (disabled ? "none" : void 0),
|
|
582
|
+
rightSectionWidth: rightSectionWidth ?? `var(--ni-right-section-width-${size || "sm"})`,
|
|
583
|
+
allowLeadingZeros,
|
|
584
|
+
allowedDecimalSeparators,
|
|
585
|
+
onBlur: handleBlur,
|
|
586
|
+
attributes,
|
|
587
|
+
isAllowed: (val) => {
|
|
588
|
+
const userAllowed = isAllowed ? isAllowed(val) : true;
|
|
589
|
+
if (!userAllowed) {
|
|
590
|
+
return false;
|
|
380
591
|
}
|
|
381
|
-
|
|
592
|
+
if (clampBehavior !== "strict") {
|
|
593
|
+
return true;
|
|
594
|
+
}
|
|
595
|
+
if (!isBigIntMode) {
|
|
596
|
+
return isInRange(val.floatValue, minNumber, maxNumber);
|
|
597
|
+
}
|
|
598
|
+
if (val.value === "" || val.value === "-") {
|
|
599
|
+
return true;
|
|
600
|
+
}
|
|
601
|
+
const parsed = parseBigIntFromString(val.value);
|
|
602
|
+
if (parsed === null) {
|
|
603
|
+
return true;
|
|
604
|
+
}
|
|
605
|
+
return (minBigInt === void 0 || parsed >= minBigInt) && (maxBigInt === void 0 || parsed <= maxBigInt);
|
|
382
606
|
}
|
|
383
|
-
return isAllowed ? isAllowed(val) : true;
|
|
384
607
|
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
);
|
|
388
611
|
NumberInput.classes = { ...InputBase.classes, ...classes };
|
|
389
612
|
NumberInput.varsResolver = varsResolver;
|
|
390
613
|
NumberInput.displayName = "@mantine/core/NumberInput";
|