@salt-ds/lab 1.0.0-alpha.77 → 1.0.0-alpha.79
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/CHANGELOG.md +80 -0
- package/css/salt-lab.css +17 -13
- package/dist-cjs/calendar/useCalendarDay.js +3 -2
- package/dist-cjs/calendar/useCalendarDay.js.map +1 -1
- package/dist-cjs/form-field-legacy/FormHelperText.css.js +1 -1
- package/dist-cjs/form-field-legacy/FormLabel.css.js +1 -1
- package/dist-cjs/index.js +1 -2
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/number-input/NumberInput.css.js +1 -1
- package/dist-cjs/number-input/NumberInput.js +201 -131
- package/dist-cjs/number-input/NumberInput.js.map +1 -1
- package/dist-cjs/tabs-next/TabNextTrigger.css.js +1 -1
- package/dist-es/calendar/useCalendarDay.js +3 -2
- package/dist-es/calendar/useCalendarDay.js.map +1 -1
- package/dist-es/form-field-legacy/FormHelperText.css.js +1 -1
- package/dist-es/form-field-legacy/FormLabel.css.js +1 -1
- package/dist-es/index.js +1 -2
- package/dist-es/index.js.map +1 -1
- package/dist-es/number-input/NumberInput.css.js +1 -1
- package/dist-es/number-input/NumberInput.js +201 -132
- package/dist-es/number-input/NumberInput.js.map +1 -1
- package/dist-es/tabs-next/TabNextTrigger.css.js +1 -1
- package/dist-types/number-input/NumberInput.d.ts +28 -15
- package/dist-types/number-input/index.d.ts +0 -1
- package/package.json +4 -4
- package/dist-cjs/number-input/internal/useCaret.js +0 -34
- package/dist-cjs/number-input/internal/useCaret.js.map +0 -1
- package/dist-cjs/number-input/internal/utils.js +0 -78
- package/dist-cjs/number-input/internal/utils.js.map +0 -1
- package/dist-cjs/number-input/useNumberInput.js +0 -107
- package/dist-cjs/number-input/useNumberInput.js.map +0 -1
- package/dist-es/number-input/internal/useCaret.js +0 -32
- package/dist-es/number-input/internal/useCaret.js.map +0 -1
- package/dist-es/number-input/internal/utils.js +0 -69
- package/dist-es/number-input/internal/utils.js.map +0 -1
- package/dist-es/number-input/useNumberInput.js +0 -105
- package/dist-es/number-input/useNumberInput.js.map +0 -1
- package/dist-types/number-input/internal/useCaret.d.ts +0 -5
- package/dist-types/number-input/internal/utils.d.ts +0 -8
- package/dist-types/number-input/useNumberInput.d.ts +0 -33
|
@@ -6,31 +6,55 @@ var styles = require('@salt-ds/styles');
|
|
|
6
6
|
var window = require('@salt-ds/window');
|
|
7
7
|
var clsx = require('clsx');
|
|
8
8
|
var react = require('react');
|
|
9
|
-
var
|
|
10
|
-
var utils = require('./internal/utils.js');
|
|
9
|
+
var useActivateWhileMouseDown = require('./internal/useActivateWhileMouseDown.js');
|
|
11
10
|
var NumberInput$1 = require('./NumberInput.css.js');
|
|
12
|
-
var useNumberInput = require('./useNumberInput.js');
|
|
13
11
|
|
|
14
12
|
const withBaseName = core.makePrefixer("saltNumberInput");
|
|
13
|
+
const isOutOfRange = (value, min, max) => {
|
|
14
|
+
if (typeof value === "string" && !value.length) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
const floatValue = typeof value === "string" ? Number.parseFloat(value) : value;
|
|
18
|
+
return Number.isNaN(floatValue) || floatValue > max || floatValue < min;
|
|
19
|
+
};
|
|
20
|
+
function getNumberPrecision(num) {
|
|
21
|
+
const numStr = String(num);
|
|
22
|
+
if (numStr.includes("e") || numStr.includes("E")) {
|
|
23
|
+
const [base, exponent] = numStr.split(/[eE]/);
|
|
24
|
+
const decimalPart = base.split(".")[1] || "";
|
|
25
|
+
const precision = decimalPart.length - Number.parseInt(exponent, 10);
|
|
26
|
+
return Math.max(0, precision);
|
|
27
|
+
}
|
|
28
|
+
if (numStr.includes(".")) {
|
|
29
|
+
return numStr.split(".")[1].length;
|
|
30
|
+
}
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
const defaultPattern = (inputValue) => /^[+-]?(\d+(\.\d*)?|\.\d*)?$/.test(inputValue);
|
|
15
34
|
const NumberInput = react.forwardRef(
|
|
16
35
|
function NumberInput2({
|
|
17
|
-
|
|
36
|
+
"aria-valuetext": ariaValueTextProp,
|
|
37
|
+
bordered,
|
|
18
38
|
className: classNameProp,
|
|
19
|
-
clamp
|
|
39
|
+
clamp,
|
|
40
|
+
decimalScale: decimalScaleProp,
|
|
20
41
|
disabled,
|
|
21
42
|
emptyReadOnlyMarker = "\u2014",
|
|
22
43
|
endAdornment,
|
|
23
|
-
format,
|
|
44
|
+
format: formatProp,
|
|
24
45
|
hideButtons,
|
|
25
46
|
id: idProp,
|
|
47
|
+
pattern = defaultPattern,
|
|
26
48
|
inputProps: inputPropsProp = {},
|
|
27
49
|
inputRef: inputRefProp,
|
|
28
50
|
max = Number.MAX_SAFE_INTEGER,
|
|
29
51
|
min = Number.MIN_SAFE_INTEGER,
|
|
30
|
-
|
|
31
|
-
|
|
52
|
+
onBlur,
|
|
53
|
+
onChange,
|
|
54
|
+
onMouseUp,
|
|
55
|
+
onNumberChange: onNumberChangeProp,
|
|
56
|
+
parse: parseProp,
|
|
32
57
|
placeholder,
|
|
33
|
-
decimalScale: decimalScaleProp,
|
|
34
58
|
readOnly: readOnlyProp,
|
|
35
59
|
startAdornment,
|
|
36
60
|
step = 1,
|
|
@@ -39,7 +63,7 @@ const NumberInput = react.forwardRef(
|
|
|
39
63
|
validationStatus: validationStatusProp,
|
|
40
64
|
value: valueProp,
|
|
41
65
|
variant = "primary",
|
|
42
|
-
defaultValue: defaultValueProp
|
|
66
|
+
defaultValue: defaultValueProp,
|
|
43
67
|
...restProps
|
|
44
68
|
}, ref) {
|
|
45
69
|
const targetWindow = window.useWindow();
|
|
@@ -61,130 +85,145 @@ const NumberInput = react.forwardRef(
|
|
|
61
85
|
const isDisabled = disabled || formFieldDisabled;
|
|
62
86
|
const isReadOnly = readOnlyProp || formFieldReadOnly;
|
|
63
87
|
const validationStatus = formFieldValidationStatus ?? validationStatusProp;
|
|
64
|
-
const isEmptyReadOnly = isReadOnly && !defaultValueProp && !valueProp;
|
|
65
|
-
const defaultValue = isEmptyReadOnly ? emptyReadOnlyMarker : defaultValueProp;
|
|
66
88
|
const validationStatusId = core.useId(idProp);
|
|
67
89
|
const inputRef = react.useRef(null);
|
|
68
90
|
const handleInputRef = core.useForkRef(inputRefProp, inputRef);
|
|
69
|
-
const { IncreaseIcon, DecreaseIcon } = core.useIcon();
|
|
70
91
|
const {
|
|
71
92
|
"aria-describedby": inputDescribedBy,
|
|
72
93
|
"aria-labelledby": inputLabelledBy,
|
|
73
94
|
className: inputClassName,
|
|
74
95
|
onBlur: inputOnBlur,
|
|
75
|
-
onChange: inputOnChange,
|
|
76
96
|
onFocus: inputOnFocus,
|
|
77
97
|
required: inputRequired,
|
|
78
98
|
onKeyDown: inputOnKeyDown,
|
|
79
99
|
...restInputProps
|
|
80
100
|
} = inputPropsProp;
|
|
81
101
|
const isRequired = formFieldRequired ? ["required", "asterisk"].includes(formFieldRequired) : inputRequired;
|
|
82
|
-
const isAdjustingRef = react.useRef(false);
|
|
83
|
-
const [isEditing, setIsEditing] = react.useState(false);
|
|
84
102
|
const [isFocused, setIsFocused] = react.useState(false);
|
|
85
|
-
const [
|
|
86
|
-
|
|
87
|
-
});
|
|
103
|
+
const [isEditing, setIsEditing] = react.useState(false);
|
|
104
|
+
const { DecreaseIcon, IncreaseIcon } = core.useIcon();
|
|
88
105
|
const [value, setValue] = core.useControlled({
|
|
89
|
-
controlled: valueProp,
|
|
90
|
-
default:
|
|
106
|
+
controlled: valueProp !== void 0 ? String(valueProp) : void 0,
|
|
107
|
+
default: String(defaultValueProp ?? ""),
|
|
91
108
|
name: "NumberInput",
|
|
92
109
|
state: "value"
|
|
93
110
|
});
|
|
94
|
-
const decimalScale = decimalScaleProp || Math.max(
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
111
|
+
const decimalScale = decimalScaleProp || Math.max(getNumberPrecision(value), getNumberPrecision(step));
|
|
112
|
+
const defaultFormat = (value2) => {
|
|
113
|
+
const sanitized = value2.trim();
|
|
114
|
+
if (!sanitized.length) {
|
|
115
|
+
return "";
|
|
116
|
+
}
|
|
117
|
+
const floatValue2 = Number.parseFloat(sanitized);
|
|
118
|
+
const updatedValue = Number.isNaN(floatValue2) ? sanitized : floatValue2.toFixed(decimalScale);
|
|
119
|
+
return String(updatedValue);
|
|
99
120
|
};
|
|
100
|
-
const {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
react.useEffect(() => {
|
|
124
|
-
const formatValue = () => {
|
|
125
|
-
const sanitizedValue = utils.sanitizeInput(value);
|
|
126
|
-
const floatValue = utils.toFloat(sanitizedValue);
|
|
127
|
-
if (!isAdjustingRef.current && (isEditing || utils.isEmpty(value) || Number.isNaN(floatValue) || isReadOnly)) {
|
|
128
|
-
return value;
|
|
129
|
-
}
|
|
130
|
-
if (isAdjustingRef.current) {
|
|
131
|
-
return clampAndFix(utils.toFloat(value));
|
|
121
|
+
const defaultParse = (value2) => {
|
|
122
|
+
const sanitizedValue = value2.trim();
|
|
123
|
+
if (!sanitizedValue.length) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
if (sanitizedValue === "." || sanitizedValue === "+" || sanitizedValue === "-") {
|
|
127
|
+
return 0;
|
|
128
|
+
}
|
|
129
|
+
const floatString = Number.parseFloat(value2).toFixed(decimalScale);
|
|
130
|
+
return Number.parseFloat(floatString);
|
|
131
|
+
};
|
|
132
|
+
const format = formatProp ?? defaultFormat;
|
|
133
|
+
const parse = parseProp ?? defaultParse;
|
|
134
|
+
const lastCommitValue = react.useRef(value);
|
|
135
|
+
const commit = (event, newNumber, newInputValue) => {
|
|
136
|
+
let safeNumber = newNumber;
|
|
137
|
+
if (safeNumber !== null && !Number.isNaN(safeNumber)) {
|
|
138
|
+
safeNumber = Math.max(
|
|
139
|
+
Number.MIN_SAFE_INTEGER,
|
|
140
|
+
Math.min(Number.MAX_SAFE_INTEGER, safeNumber)
|
|
141
|
+
);
|
|
142
|
+
if (clamp) {
|
|
143
|
+
safeNumber = Math.max(min, Math.min(max, safeNumber));
|
|
132
144
|
}
|
|
133
|
-
const clampedValue = clampAndFix(floatValue);
|
|
134
|
-
return format ? format(clampedValue) : clampedValue;
|
|
135
|
-
};
|
|
136
|
-
const updatedValue = formatValue();
|
|
137
|
-
setDisplayValue(updatedValue);
|
|
138
|
-
}, [value, isEditing, isReadOnly, format, clamp, decimalScale, min, max]);
|
|
139
|
-
react.useLayoutEffect(() => {
|
|
140
|
-
if (isAdjustingRef.current) {
|
|
141
|
-
resetCaret();
|
|
142
|
-
} else {
|
|
143
|
-
restoreCaret();
|
|
144
145
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
146
|
+
const commitValue = safeNumber !== null && !Number.isNaN(safeNumber) ? safeNumber.toFixed(decimalScale) : newInputValue;
|
|
147
|
+
if (commitValue !== value) {
|
|
148
|
+
setValue(commitValue);
|
|
149
|
+
}
|
|
150
|
+
if (lastCommitValue.current !== commitValue) {
|
|
151
|
+
onChange == null ? void 0 : onChange(event, commitValue);
|
|
152
|
+
onNumberChangeProp == null ? void 0 : onNumberChangeProp(event, safeNumber);
|
|
153
|
+
}
|
|
154
|
+
lastCommitValue.current = commitValue;
|
|
153
155
|
};
|
|
154
|
-
const
|
|
156
|
+
const handleBlur = (event) => {
|
|
155
157
|
setIsFocused(false);
|
|
156
|
-
|
|
158
|
+
onBlur == null ? void 0 : onBlur(event);
|
|
159
|
+
};
|
|
160
|
+
const handleInputBlur = (event) => {
|
|
157
161
|
setIsEditing(false);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
inputOnBlur == null ? void 0 : inputOnBlur(event);
|
|
163
|
+
const parsedValue = parse(value);
|
|
164
|
+
commit(event, parsedValue, value);
|
|
165
|
+
};
|
|
166
|
+
const handleInputFocus = (event) => {
|
|
167
|
+
setIsEditing(false);
|
|
168
|
+
inputOnFocus == null ? void 0 : inputOnFocus(event);
|
|
169
|
+
};
|
|
170
|
+
const handleInputChange = (event) => {
|
|
171
|
+
const inputValue = event.currentTarget.value;
|
|
172
|
+
if (!inputValue.length) {
|
|
173
|
+
setValue("");
|
|
174
|
+
onChange == null ? void 0 : onChange(event, "");
|
|
162
175
|
return;
|
|
163
176
|
}
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
setValue(
|
|
169
|
-
|
|
177
|
+
const validValue = pattern ? pattern(inputValue) : true;
|
|
178
|
+
if (validValue) {
|
|
179
|
+
setIsEditing(true);
|
|
180
|
+
onChange == null ? void 0 : onChange(event, event.target.value);
|
|
181
|
+
setValue(inputValue);
|
|
182
|
+
} else {
|
|
183
|
+
event.preventDefault();
|
|
170
184
|
}
|
|
171
|
-
const formattedValue = format ? format(clampedValue) : clampedValue;
|
|
172
|
-
setDisplayValue(formattedValue);
|
|
173
|
-
inputOnBlur == null ? void 0 : inputOnBlur(event);
|
|
174
185
|
};
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (
|
|
186
|
+
const decrementValue = (event, block) => {
|
|
187
|
+
const decrementStep = (block ? stepMultiplier : 1) * step;
|
|
188
|
+
let adjustedValue = parse(value) ?? 0;
|
|
189
|
+
if (Number.isNaN(adjustedValue)) {
|
|
179
190
|
return;
|
|
180
191
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
onChangeProp == null ? void 0 : onChangeProp(event, parsed);
|
|
192
|
+
adjustedValue -= decrementStep;
|
|
193
|
+
commit(event ?? null, adjustedValue, String(adjustedValue));
|
|
184
194
|
};
|
|
195
|
+
let floatValue = parse(value) ?? 0;
|
|
196
|
+
floatValue = Math.max(
|
|
197
|
+
Number.MIN_SAFE_INTEGER,
|
|
198
|
+
Math.min(Number.MAX_SAFE_INTEGER, floatValue)
|
|
199
|
+
);
|
|
200
|
+
if (clamp) {
|
|
201
|
+
floatValue = Math.max(min, Math.min(max, floatValue));
|
|
202
|
+
}
|
|
203
|
+
const { activate: activateDecrement } = useActivateWhileMouseDown.useActivateWhileMouseDown(
|
|
204
|
+
decrementValue,
|
|
205
|
+
floatValue <= min
|
|
206
|
+
);
|
|
207
|
+
const incrementValue = (event, block) => {
|
|
208
|
+
const incrementStep = (block ? stepMultiplier : 1) * step;
|
|
209
|
+
let adjustedValue = parse(value) ?? 0;
|
|
210
|
+
if (Number.isNaN(adjustedValue)) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
adjustedValue += incrementStep;
|
|
214
|
+
commit(event ?? null, adjustedValue, String(adjustedValue));
|
|
215
|
+
};
|
|
216
|
+
react.useEffect(() => {
|
|
217
|
+
var _a;
|
|
218
|
+
if (isFocused) {
|
|
219
|
+
(_a = inputRef.current) == null ? void 0 : _a.focus();
|
|
220
|
+
}
|
|
221
|
+
}, [isFocused]);
|
|
222
|
+
const { activate: activateIncrement } = useActivateWhileMouseDown.useActivateWhileMouseDown(
|
|
223
|
+
incrementValue,
|
|
224
|
+
floatValue >= max
|
|
225
|
+
);
|
|
185
226
|
const handleInputKeyDown = (event) => {
|
|
186
|
-
setIsEditing(true);
|
|
187
|
-
isAdjustingRef.current = false;
|
|
188
227
|
switch (event.key) {
|
|
189
228
|
case "ArrowUp": {
|
|
190
229
|
event.preventDefault();
|
|
@@ -200,14 +239,16 @@ const NumberInput = react.forwardRef(
|
|
|
200
239
|
}
|
|
201
240
|
case "Home": {
|
|
202
241
|
event.preventDefault();
|
|
203
|
-
|
|
204
|
-
|
|
242
|
+
const newValue = String(min);
|
|
243
|
+
setValue(newValue);
|
|
244
|
+
commit(event, min, newValue);
|
|
205
245
|
break;
|
|
206
246
|
}
|
|
207
247
|
case "End": {
|
|
208
248
|
event.preventDefault();
|
|
209
|
-
|
|
210
|
-
|
|
249
|
+
const newValue = String(max);
|
|
250
|
+
setValue(newValue);
|
|
251
|
+
commit(event, max, newValue);
|
|
211
252
|
break;
|
|
212
253
|
}
|
|
213
254
|
case "PageUp": {
|
|
@@ -223,9 +264,40 @@ const NumberInput = react.forwardRef(
|
|
|
223
264
|
}
|
|
224
265
|
inputOnKeyDown == null ? void 0 : inputOnKeyDown(event);
|
|
225
266
|
};
|
|
226
|
-
const
|
|
227
|
-
|
|
267
|
+
const handleIncrementMouseDown = (event, disableIncrement2) => {
|
|
268
|
+
event.preventDefault();
|
|
269
|
+
if (!disableIncrement2) {
|
|
270
|
+
setIsEditing(false);
|
|
271
|
+
activateIncrement(event);
|
|
272
|
+
} else if (inputRef.current) {
|
|
273
|
+
inputRef.current.select();
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const handleDecrementMouseDown = (event, disableDecrement2) => {
|
|
277
|
+
event.preventDefault();
|
|
278
|
+
if (!disableDecrement2) {
|
|
279
|
+
setIsEditing(false);
|
|
280
|
+
activateDecrement(event);
|
|
281
|
+
} else if (inputRef.current) {
|
|
282
|
+
inputRef.current.select();
|
|
283
|
+
}
|
|
228
284
|
};
|
|
285
|
+
const handleContainerMouseUp = (event) => {
|
|
286
|
+
setIsFocused(true);
|
|
287
|
+
onMouseUp == null ? void 0 : onMouseUp(event);
|
|
288
|
+
};
|
|
289
|
+
let renderedValue;
|
|
290
|
+
if (isEditing) {
|
|
291
|
+
renderedValue = value;
|
|
292
|
+
} else if (!(value == null ? void 0 : value.length)) {
|
|
293
|
+
renderedValue = "";
|
|
294
|
+
} else {
|
|
295
|
+
renderedValue = format(
|
|
296
|
+
Number.isNaN(floatValue) ? value : String(floatValue)
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
const disableDecrement = disabled || floatValue - step < min;
|
|
300
|
+
const disableIncrement = disabled || floatValue + step > max;
|
|
229
301
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
230
302
|
"div",
|
|
231
303
|
{
|
|
@@ -242,6 +314,8 @@ const NumberInput = react.forwardRef(
|
|
|
242
314
|
},
|
|
243
315
|
classNameProp
|
|
244
316
|
),
|
|
317
|
+
onBlur: handleBlur,
|
|
318
|
+
onMouseUp: handleContainerMouseUp,
|
|
245
319
|
...restProps,
|
|
246
320
|
ref,
|
|
247
321
|
children: [
|
|
@@ -249,17 +323,9 @@ const NumberInput = react.forwardRef(
|
|
|
249
323
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
250
324
|
"input",
|
|
251
325
|
{
|
|
252
|
-
"aria-describedby": clsx.clsx(
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
inputDescribedBy
|
|
256
|
-
),
|
|
257
|
-
"aria-labelledby": clsx.clsx(formFieldLabelledBy, inputLabelledBy),
|
|
258
|
-
"aria-invalid": !isReadOnly ? utils.isOutOfRange(value, min, max) || validationStatus === "error" : void 0,
|
|
259
|
-
"aria-valuemax": !isReadOnly ? max : void 0,
|
|
260
|
-
"aria-valuemin": !isReadOnly ? min : void 0,
|
|
261
|
-
"aria-valuenow": value && !Number.isNaN(utils.toFloat(value)) && !isReadOnly ? utils.toFloat((parse == null ? void 0 : parse(value)) || value) : void 0,
|
|
262
|
-
...!isReadOnly && { "aria-valuetext": value.toString() },
|
|
326
|
+
"aria-describedby": clsx.clsx(formFieldDescribedBy, inputDescribedBy) || void 0,
|
|
327
|
+
"aria-labelledby": clsx.clsx(formFieldLabelledBy, inputLabelledBy) || void 0,
|
|
328
|
+
"aria-invalid": !isReadOnly && renderedValue.length ? isOutOfRange(floatValue, min, max) || validationStatus === "error" : void 0,
|
|
263
329
|
className: clsx.clsx(
|
|
264
330
|
withBaseName("input"),
|
|
265
331
|
withBaseName(`inputTextAlign${core.capitalize(textAlign)}`),
|
|
@@ -269,16 +335,19 @@ const NumberInput = react.forwardRef(
|
|
|
269
335
|
onBlur: handleInputBlur,
|
|
270
336
|
onChange: handleInputChange,
|
|
271
337
|
onFocus: handleInputFocus,
|
|
272
|
-
onKeyDown: handleInputKeyDown,
|
|
273
|
-
onBeforeInput: handleBeforeInput,
|
|
338
|
+
onKeyDown: isReadOnly ? void 0 : handleInputKeyDown,
|
|
274
339
|
placeholder,
|
|
275
340
|
readOnly: isReadOnly,
|
|
276
341
|
"aria-readonly": isReadOnly ? "true" : void 0,
|
|
277
342
|
ref: handleInputRef,
|
|
278
343
|
required: isRequired,
|
|
344
|
+
"aria-valuemax": !isReadOnly && renderedValue.length ? max : void 0,
|
|
345
|
+
"aria-valuemin": !isReadOnly && renderedValue.length ? min : void 0,
|
|
346
|
+
"aria-valuenow": !isReadOnly ? floatValue : void 0,
|
|
347
|
+
"aria-valuetext": !isReadOnly ? renderedValue.length ? ariaValueTextProp ?? renderedValue : "Empty" : void 0,
|
|
279
348
|
role: isReadOnly ? "textbox" : "spinbutton",
|
|
280
349
|
tabIndex: isDisabled ? -1 : 0,
|
|
281
|
-
value:
|
|
350
|
+
value: isReadOnly && renderedValue.length === 0 ? emptyReadOnlyMarker : renderedValue,
|
|
282
351
|
...restInputProps
|
|
283
352
|
}
|
|
284
353
|
),
|
|
@@ -289,24 +358,24 @@ const NumberInput = react.forwardRef(
|
|
|
289
358
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
290
359
|
core.Button,
|
|
291
360
|
{
|
|
292
|
-
|
|
293
|
-
withBaseName("numberButton"),
|
|
294
|
-
withBaseName("numberButtonIncrement")
|
|
295
|
-
),
|
|
361
|
+
"aria-hidden": true,
|
|
296
362
|
appearance: "transparent",
|
|
297
|
-
|
|
363
|
+
tabIndex: -1,
|
|
364
|
+
disabled: disableIncrement,
|
|
365
|
+
className: withBaseName("increment"),
|
|
366
|
+
onMouseDown: (event) => handleIncrementMouseDown(event, disableIncrement),
|
|
298
367
|
children: /* @__PURE__ */ jsxRuntime.jsx(IncreaseIcon, { "aria-hidden": true })
|
|
299
368
|
}
|
|
300
369
|
),
|
|
301
370
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
302
371
|
core.Button,
|
|
303
372
|
{
|
|
304
|
-
|
|
305
|
-
withBaseName("numberButton"),
|
|
306
|
-
withBaseName("numberButtonDecrement")
|
|
307
|
-
),
|
|
373
|
+
"aria-hidden": true,
|
|
308
374
|
appearance: "transparent",
|
|
309
|
-
|
|
375
|
+
tabIndex: -1,
|
|
376
|
+
disabled: disableDecrement,
|
|
377
|
+
className: withBaseName("decrement"),
|
|
378
|
+
onMouseDown: (event) => handleDecrementMouseDown(event, disableDecrement),
|
|
310
379
|
children: /* @__PURE__ */ jsxRuntime.jsx(DecreaseIcon, { "aria-hidden": true })
|
|
311
380
|
}
|
|
312
381
|
)
|
|
@@ -318,4 +387,5 @@ const NumberInput = react.forwardRef(
|
|
|
318
387
|
);
|
|
319
388
|
|
|
320
389
|
exports.NumberInput = NumberInput;
|
|
390
|
+
exports.isOutOfRange = isOutOfRange;
|
|
321
391
|
//# sourceMappingURL=NumberInput.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NumberInput.js","sources":["../src/number-input/NumberInput.tsx"],"sourcesContent":["import {\n Button,\n capitalize,\n makePrefixer,\n StatusAdornment,\n useControlled,\n useForkRef,\n useFormFieldProps,\n useIcon,\n useId,\n type ValidationStatus,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ChangeEvent,\n type ComponentPropsWithoutRef,\n type FocusEvent,\n forwardRef,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n type SyntheticEvent,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport useCaret from \"./internal/useCaret\";\nimport {\n clampToRange,\n getNumberPrecision,\n isEmpty,\n isOutOfRange,\n sanitizeInput,\n toFloat,\n} from \"./internal/utils\";\nimport numberInputCss from \"./NumberInput.css\";\nimport { useNumberInput } from \"./useNumberInput\";\n\nconst withBaseName = makePrefixer(\"saltNumberInput\");\n\nexport interface NumberInputProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n /**\n * Styling variant with full border.\n * @default false\n */\n bordered?: boolean;\n /**\n * A boolean that, when true, ensures the input value is clamped within the specified min and max range upon losing focus.\n * @default false\n */\n clamp?: boolean;\n /**\n * The default value. Use when the component is uncontrolled.\n */\n defaultValue?: number | string;\n /**\n * Disable the `NumberInput`.\n * @default false\n */\n disabled?: boolean;\n /**\n * The marker to use in an empty read only Input.\n * Use `''` to disable this feature.\n * @default \"—\"\n */\n emptyReadOnlyMarker?: string;\n /**\n * End adornment component.\n */\n endAdornment?: ReactNode;\n /**\n * A callback to format the value of the `NumberInput`.\n */\n format?: (value: number | string) => string | number;\n /**\n * Hide the number buttons.\n * @default false\n */\n hideButtons?: boolean;\n /**\n * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.\n */\n inputProps?: InputHTMLAttributes<HTMLInputElement>;\n /**\n * Optional ref for the input component.\n */\n inputRef?: Ref<HTMLInputElement>;\n /**\n * The maximum value that can be selected.\n * @default Number.MAX_SAFE_INTEGER\n */\n max?: number;\n /**\n * The minimum value that can be selected.\n * @default Number.MIN_SAFE_INTEGER\n */\n min?: number;\n /**\n * Callback function that is triggered when the value of the `NumberInput` changes.\n *\n * @param event - The event that triggers the value change. This may be `undefined` during a long press on the increment or decrement buttons.\n * @param value - The new value of the `NumberInput`, which can be a number or a string.\n */\n onChange?: (\n event: SyntheticEvent | undefined,\n value: number | string,\n ) => void;\n /**\n *\n * A callback to parse the value of the `NumberInput`. To be used alongside\n * the `format` callback.\n */\n parse?: (value: number | string) => string | number;\n /**\n * A string displayed in a dimmed color when the `NumberInput` value is empty.\n */\n placeholder?: string;\n /**\n * The number of decimal places allowed. Defaults to the decimal scale of either the initial value provided or the step, whichever is greater.\n */\n decimalScale?: number;\n /**\n * A boolean property that controls the editability of the `NumberInput`.\n * - When set to `true`, the `NumberInput` becomes read-only, preventing user edits.\n * - When set to `false` or omitted, the `NumberInput` is editable by the user.\n */\n readOnly?: boolean;\n /**\n * Start adornment component.\n */\n startAdornment?: ReactNode;\n /**\n * The amount to increment or decrement the value by when using the `NumberInput` buttons or Up Arrow and Down Arrow keys.\n * @default 1\n */\n step?: number;\n /**\n * Defines the factor by which the step value is multiplied to determine the maximum increment or decrement when the Shift key\n * is held while pressing the Up Arrow or Down Arrow keys for faster adjustments of the value.\n * @default 2\n */\n stepMultiplier?: number;\n /**\n * Specifies the alignment of the text within the `NumberInput`.\n *\n * @default \"left\"\n */\n textAlign?: \"left\" | \"center\" | \"right\";\n /**\n * Validation status.\n */\n validationStatus?: Extract<ValidationStatus, \"error\" | \"warning\" | \"success\">;\n /**\n * Styling variant.\n * @default \"primary\"\n */\n variant?: \"primary\" | \"secondary\";\n /**\n * Value of the `NumberInput`, to be used when in a controlled state.\n */\n value?: number | string;\n}\n\nexport const NumberInput = forwardRef<HTMLDivElement, NumberInputProps>(\n function NumberInput(\n {\n bordered = false,\n className: classNameProp,\n clamp = false,\n disabled,\n emptyReadOnlyMarker = \"—\",\n endAdornment,\n format,\n hideButtons,\n id: idProp,\n inputProps: inputPropsProp = {},\n inputRef: inputRefProp,\n max = Number.MAX_SAFE_INTEGER,\n min = Number.MIN_SAFE_INTEGER,\n onChange: onChangeProp,\n parse,\n placeholder,\n decimalScale: decimalScaleProp,\n readOnly: readOnlyProp,\n startAdornment,\n step = 1,\n stepMultiplier = 2,\n textAlign = \"left\",\n validationStatus: validationStatusProp,\n value: valueProp,\n variant = \"primary\",\n defaultValue: defaultValueProp = \"\",\n ...restProps\n },\n ref,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-number-input\",\n css: numberInputCss,\n window: targetWindow,\n });\n\n const {\n a11yProps: {\n \"aria-describedby\": formFieldDescribedBy,\n \"aria-labelledby\": formFieldLabelledBy,\n } = {},\n disabled: formFieldDisabled,\n readOnly: formFieldReadOnly,\n necessity: formFieldRequired,\n validationStatus: formFieldValidationStatus,\n } = useFormFieldProps();\n\n const isDisabled = disabled || formFieldDisabled;\n const isReadOnly = readOnlyProp || formFieldReadOnly;\n const validationStatus = formFieldValidationStatus ?? validationStatusProp;\n const isEmptyReadOnly = isReadOnly && !defaultValueProp && !valueProp;\n const defaultValue = isEmptyReadOnly\n ? emptyReadOnlyMarker\n : defaultValueProp;\n\n const validationStatusId = useId(idProp);\n const inputRef = useRef<HTMLInputElement>(null);\n const handleInputRef = useForkRef(inputRefProp, inputRef);\n const { IncreaseIcon, DecreaseIcon } = useIcon();\n\n const {\n \"aria-describedby\": inputDescribedBy,\n \"aria-labelledby\": inputLabelledBy,\n className: inputClassName,\n onBlur: inputOnBlur,\n onChange: inputOnChange,\n onFocus: inputOnFocus,\n required: inputRequired,\n onKeyDown: inputOnKeyDown,\n ...restInputProps\n } = inputPropsProp;\n\n const isRequired = formFieldRequired\n ? [\"required\", \"asterisk\"].includes(formFieldRequired)\n : inputRequired;\n\n const isAdjustingRef = useRef<boolean>(false);\n const [isEditing, setIsEditing] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n const [recordCaret, restoreCaret, resetCaret] = useCaret({\n inputRef,\n });\n\n const [value, setValue] = useControlled({\n controlled: valueProp,\n default: defaultValue,\n name: \"NumberInput\",\n state: \"value\",\n });\n\n const decimalScale =\n decimalScaleProp ||\n Math.max(getNumberPrecision(value), getNumberPrecision(step));\n\n const [displayValue, setDisplayValue] = useState<string | number>(value);\n\n const clampAndFix = (value: number) => {\n const clampedValue = clamp ? clampToRange(min, max, value) : value;\n return !format ? clampedValue.toFixed(decimalScale) : clampedValue;\n };\n\n const {\n decrementButtonProps,\n decrementValue,\n incrementButtonProps,\n incrementValue,\n } = useNumberInput({\n clampAndFix,\n decimalScale,\n disabled,\n format,\n inputRef,\n isAdjustingRef,\n max,\n min,\n onChange: onChangeProp,\n parse,\n readOnly: isReadOnly,\n setIsEditing,\n setValue,\n step,\n stepMultiplier,\n value,\n });\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: We do not want to re-render when display value changes\n useEffect(() => {\n const formatValue = () => {\n const sanitizedValue = sanitizeInput(value);\n const floatValue = toFloat(sanitizedValue);\n if (\n !isAdjustingRef.current &&\n (isEditing ||\n isEmpty(value) ||\n Number.isNaN(floatValue) ||\n isReadOnly)\n ) {\n return value;\n }\n if (isAdjustingRef.current) {\n return clampAndFix(toFloat(value));\n }\n const clampedValue = clampAndFix(floatValue);\n return format ? format(clampedValue) : clampedValue;\n };\n const updatedValue = formatValue();\n setDisplayValue(updatedValue);\n }, [value, isEditing, isReadOnly, format, clamp, decimalScale, min, max]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Need to restore caret position when value changes.\n useLayoutEffect(() => {\n if (isAdjustingRef.current) {\n resetCaret();\n } else {\n restoreCaret();\n }\n }, [displayValue, value]);\n\n const handleInputFocus = (event: FocusEvent<HTMLInputElement>) => {\n setIsFocused(true);\n if (isReadOnly) return;\n const parsedValue = parse?.(value) ?? value;\n const updatedValue = !isEmpty(parsedValue)\n ? clampAndFix(toFloat(parsedValue))\n : parsedValue;\n setDisplayValue(updatedValue);\n inputOnFocus?.(event);\n };\n\n const handleInputBlur = (event: FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n if (isReadOnly) return;\n setIsEditing(false);\n isAdjustingRef.current = false;\n resetCaret();\n const inputValue = event.target.value;\n if (isEmpty(inputValue)) {\n return;\n }\n const sanitizedValue = sanitizeInput(event.target.value);\n const floatValue = toFloat(sanitizedValue);\n const clampedValue = clampAndFix(floatValue);\n // Update the value if it has changed\n if (clampedValue.toString() !== value.toString()) {\n setValue(clampedValue);\n onChangeProp?.(event, clampedValue);\n }\n // Ensure the displayValue is updated with the formatted value\n const formattedValue = format ? format(clampedValue) : clampedValue;\n setDisplayValue(formattedValue);\n inputOnBlur?.(event);\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n recordCaret();\n const raw = sanitizeInput(event.target.value);\n if (raw.toString() === value.toString()) {\n return;\n }\n const parsed = parse && !isEditing ? parse(raw) : raw;\n setValue(parsed);\n onChangeProp?.(event, parsed);\n };\n\n const handleInputKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n setIsEditing(true);\n isAdjustingRef.current = false;\n\n switch (event.key) {\n case \"ArrowUp\": {\n event.preventDefault();\n const block = event.shiftKey;\n incrementValue(event, block);\n break;\n }\n case \"ArrowDown\": {\n event.preventDefault();\n const block = event.shiftKey;\n decrementValue(event, block);\n break;\n }\n case \"Home\": {\n event.preventDefault();\n setValue(min);\n onChangeProp?.(event, min);\n break;\n }\n case \"End\": {\n event.preventDefault();\n setValue(max);\n onChangeProp?.(event, max);\n break;\n }\n case \"PageUp\": {\n event.preventDefault();\n incrementValue(event, true);\n break;\n }\n case \"PageDown\": {\n event.preventDefault();\n decrementValue(event, true);\n break;\n }\n }\n inputOnKeyDown?.(event);\n };\n\n const handleBeforeInput = () => {\n setIsEditing(true);\n };\n\n return (\n <div\n className={clsx(\n withBaseName(),\n withBaseName(variant),\n {\n [withBaseName(\"focused\")]: isFocused,\n [withBaseName(\"disabled\")]: isDisabled,\n [withBaseName(\"readOnly\")]: isReadOnly,\n [withBaseName(\"hiddenButtons\")]: hideButtons,\n [withBaseName(validationStatus || \"\")]: validationStatus,\n [withBaseName(\"bordered\")]: bordered,\n },\n classNameProp,\n )}\n {...restProps}\n ref={ref}\n >\n {startAdornment && (\n <div className={withBaseName(\"startAdornmentContainer\")}>\n {startAdornment}\n </div>\n )}\n <input\n aria-describedby={clsx(\n validationStatusId,\n formFieldDescribedBy,\n inputDescribedBy,\n )}\n aria-labelledby={clsx(formFieldLabelledBy, inputLabelledBy)}\n aria-invalid={\n !isReadOnly\n ? isOutOfRange(value, min, max) || validationStatus === \"error\"\n : undefined\n }\n aria-valuemax={!isReadOnly ? max : undefined}\n aria-valuemin={!isReadOnly ? min : undefined}\n aria-valuenow={\n value && !Number.isNaN(toFloat(value)) && !isReadOnly\n ? toFloat(parse?.(value) || value)\n : undefined\n }\n // Workaround to have the value announced by screen reader on Safari.\n {...(!isReadOnly && { \"aria-valuetext\": value.toString() })}\n className={clsx(\n withBaseName(\"input\"),\n withBaseName(`inputTextAlign${capitalize(textAlign)}`),\n inputClassName,\n )}\n disabled={isDisabled}\n onBlur={handleInputBlur}\n onChange={handleInputChange}\n onFocus={handleInputFocus}\n onKeyDown={handleInputKeyDown}\n onBeforeInput={handleBeforeInput}\n placeholder={placeholder}\n readOnly={isReadOnly}\n aria-readonly={isReadOnly ? \"true\" : undefined}\n ref={handleInputRef}\n required={isRequired}\n // Workaround to have readonly conveyed by screen readers (https://github.com/jpmorganchase/salt-ds/issues/4586)\n role={isReadOnly ? \"textbox\" : \"spinbutton\"}\n tabIndex={isDisabled ? -1 : 0}\n value={displayValue}\n {...restInputProps}\n />\n <div className={withBaseName(\"activationIndicator\")} />\n {!isDisabled && validationStatus && (\n <StatusAdornment status={validationStatus} id={validationStatusId} />\n )}\n {endAdornment && (\n <div className={withBaseName(\"endAdornmentContainer\")}>\n {endAdornment}\n </div>\n )}\n {!isReadOnly && (\n <div className={clsx(withBaseName(\"buttonContainer\"))}>\n <Button\n className={clsx(\n withBaseName(\"numberButton\"),\n withBaseName(\"numberButtonIncrement\"),\n )}\n appearance=\"transparent\"\n {...incrementButtonProps}\n >\n <IncreaseIcon aria-hidden />\n </Button>\n <Button\n className={clsx(\n withBaseName(\"numberButton\"),\n withBaseName(\"numberButtonDecrement\"),\n )}\n appearance=\"transparent\"\n {...decrementButtonProps}\n >\n <DecreaseIcon aria-hidden />\n </Button>\n </div>\n )}\n </div>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","NumberInput","useWindow","useComponentCssInjection","numberInputCss","useFormFieldProps","useId","useRef","useForkRef","useIcon","useState","useControlled","getNumberPrecision","value","clampToRange","useNumberInput","useEffect","sanitizeInput","toFloat","isEmpty","useLayoutEffect","jsxs","clsx","jsx","isOutOfRange","capitalize","StatusAdornment","Button"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"NumberInput.js","sources":["../src/number-input/NumberInput.tsx"],"sourcesContent":["import {\n Button,\n capitalize,\n makePrefixer,\n StatusAdornment,\n useControlled,\n useForkRef,\n useFormFieldProps,\n useIcon,\n useId,\n type ValidationStatus,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ChangeEvent,\n type ComponentPropsWithoutRef,\n type FocusEvent,\n forwardRef,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type MouseEventHandler,\n type ReactNode,\n type Ref,\n type SyntheticEvent,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useActivateWhileMouseDown } from \"./internal/useActivateWhileMouseDown\";\nimport numberInputCss from \"./NumberInput.css\";\n\nconst withBaseName = makePrefixer(\"saltNumberInput\");\n\nexport interface NumberInputProps\n extends Omit<\n ComponentPropsWithoutRef<\"div\">,\n \"onChange\" | \"defaultValue\" | \"value\"\n > {\n /**\n * Styling variant with full border.\n * @default false\n */\n bordered?: boolean;\n /**\n * A boolean that, when true, ensures the input value is clamped within the specified min and max range upon losing focus.\n * @default false\n */\n clamp?: boolean;\n /**\n * The number of decimal places allowed. Defaults to the decimal scale of either the initial value provided or the step, whichever is greater.\n */\n decimalScale?: number;\n /**\n * The default value. Use when the component is uncontrolled.\n */\n defaultValue?: number | string;\n /**\n * Disable the `NumberInput`.\n * @default false\n */\n disabled?: boolean;\n /**\n * The marker to use in an empty read only Input.\n * @default \"—\"\n */\n emptyReadOnlyMarker?: string;\n /**\n * End adornment component.\n */\n endAdornment?: ReactNode;\n /**\n * A callback to format the value of the `NumberInput`.\n * value : string\n */\n format?: (value: string) => string;\n /**\n * Hide the number buttons.\n * @default false\n */\n hideButtons?: boolean;\n /**\n * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.\n */\n inputProps?: InputHTMLAttributes<HTMLInputElement>;\n /**\n * Optional ref for the input component.\n */\n inputRef?: Ref<HTMLInputElement>;\n /**\n * Callback that matches on values as you type and determines whether the value can be entered.\n */\n pattern?: (inputValue: string) => boolean;\n /**\n * The maximum value that can be selected.\n * @default Number.MAX_SAFE_INTEGER\n */\n max?: number;\n /**\n * The minimum value that can be selected.\n * @default Number.MIN_SAFE_INTEGER\n */\n min?: number;\n /**\n * Callback function that is triggered when the value changes via user input or increment/decrement.\n * Use `onNumberChange` if you want stable number, after blur or through increment/decrement\n *\n * @param event - The event that triggers the value change, can be null if called by long-press of increment/decrement\n * @param value - value as string\n */\n onChange?: (event: SyntheticEvent | null, value: string) => void;\n /**\n * Callback function that is triggered when the value changes via increment/decrement or on blur.\n *\n * @param event - The event that triggers the change, can be null if called by long-press of increment/decrement\n * @param value - The committed, parsed number value or null if an empty value\n */\n onNumberChange?: (event: SyntheticEvent | null, value: number | null) => void;\n /**\n *\n * A callback to parse the value of the `NumberInput`. To be used alongside the `format` callback.\n * Return null if you want the NumberInput to be empty.\n */\n parse?: (value: string) => number | null;\n /**\n * A string displayed in a dimmed color when the `NumberInput` value is empty.\n */\n placeholder?: string;\n /**\n * A boolean property that controls the read-only state of the `NumberInput`.\n * - When set to `true`, the `NumberInput` becomes read-only, preventing user edits.\n * - When set to `false` or omitted, the `NumberInput` is editable by the user.\n */\n readOnly?: boolean;\n /**\n * Start adornment component.\n */\n startAdornment?: ReactNode;\n /**\n * The amount to increment or decrement the value by when using the `NumberInput` buttons or Up Arrow and Down Arrow keys.\n * @default 1\n */\n step?: number;\n /**\n * Defines the factor by which the step value is multiplied to determine the maximum increment or decrement when the Shift key\n * is held while pressing the Up Arrow or Down Arrow keys for faster adjustments of the value.\n * @default 2\n */\n stepMultiplier?: number;\n /**\n * Specifies the alignment of the text within the `NumberInput`.\n *\n * @default \"left\"\n */\n textAlign?: \"left\" | \"center\" | \"right\";\n /**\n * Validation status.\n */\n validationStatus?: Extract<ValidationStatus, \"error\" | \"warning\" | \"success\">;\n /**\n * Styling variant.\n * @default \"primary\"\n */\n variant?: \"primary\" | \"secondary\";\n /**\n * Value of the `NumberInput`, to be used when in a controlled state.\n */\n value?: number | string;\n}\n\nexport const isOutOfRange = (\n value: number | string,\n min: number,\n max: number,\n) => {\n if (typeof value === \"string\" && !value.length) {\n return true;\n }\n const floatValue =\n typeof value === \"string\" ? Number.parseFloat(value) : value;\n return Number.isNaN(floatValue) || floatValue > max || floatValue < min;\n};\n\nfunction getNumberPrecision(num: number | string) {\n const numStr = String(num);\n\n if (numStr.includes(\"e\") || numStr.includes(\"E\")) {\n const [base, exponent] = numStr.split(/[eE]/);\n const decimalPart = base.split(\".\")[1] || \"\";\n const precision = decimalPart.length - Number.parseInt(exponent, 10);\n return Math.max(0, precision);\n }\n\n if (numStr.includes(\".\")) {\n return numStr.split(\".\")[1].length;\n }\n\n return 0;\n}\n\nconst defaultPattern: NumberInputProps[\"pattern\"] = (inputValue) =>\n /^[+-]?(\\d+(\\.\\d*)?|\\.\\d*)?$/.test(inputValue);\n\nexport const NumberInput = forwardRef<HTMLDivElement, NumberInputProps>(\n function NumberInput(\n {\n \"aria-valuetext\": ariaValueTextProp,\n bordered,\n className: classNameProp,\n clamp,\n decimalScale: decimalScaleProp,\n disabled,\n emptyReadOnlyMarker = \"—\",\n endAdornment,\n format: formatProp,\n hideButtons,\n id: idProp,\n pattern = defaultPattern,\n inputProps: inputPropsProp = {},\n inputRef: inputRefProp,\n max = Number.MAX_SAFE_INTEGER,\n min = Number.MIN_SAFE_INTEGER,\n onBlur,\n onChange,\n onMouseUp,\n onNumberChange: onNumberChangeProp,\n parse: parseProp,\n placeholder,\n readOnly: readOnlyProp,\n startAdornment,\n step = 1,\n stepMultiplier = 2,\n textAlign = \"left\",\n validationStatus: validationStatusProp,\n value: valueProp,\n variant = \"primary\",\n defaultValue: defaultValueProp,\n ...restProps\n },\n ref,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-number-input\",\n css: numberInputCss,\n window: targetWindow,\n });\n\n const {\n a11yProps: {\n \"aria-describedby\": formFieldDescribedBy,\n \"aria-labelledby\": formFieldLabelledBy,\n } = {},\n disabled: formFieldDisabled,\n readOnly: formFieldReadOnly,\n necessity: formFieldRequired,\n validationStatus: formFieldValidationStatus,\n } = useFormFieldProps();\n\n const isDisabled = disabled || formFieldDisabled;\n const isReadOnly = readOnlyProp || formFieldReadOnly;\n const validationStatus = formFieldValidationStatus ?? validationStatusProp;\n const validationStatusId = useId(idProp);\n const inputRef = useRef<HTMLInputElement>(null);\n const handleInputRef = useForkRef(inputRefProp, inputRef);\n\n const {\n \"aria-describedby\": inputDescribedBy,\n \"aria-labelledby\": inputLabelledBy,\n className: inputClassName,\n onBlur: inputOnBlur,\n onFocus: inputOnFocus,\n required: inputRequired,\n onKeyDown: inputOnKeyDown,\n ...restInputProps\n } = inputPropsProp;\n\n const isRequired = formFieldRequired\n ? [\"required\", \"asterisk\"].includes(formFieldRequired)\n : inputRequired;\n\n const [isFocused, setIsFocused] = useState(false);\n const [isEditing, setIsEditing] = useState(false);\n const { DecreaseIcon, IncreaseIcon } = useIcon();\n\n const [value, setValue] = useControlled({\n controlled: valueProp !== undefined ? String(valueProp) : undefined,\n default: String(defaultValueProp ?? \"\"),\n name: \"NumberInput\",\n state: \"value\",\n });\n\n const decimalScale =\n decimalScaleProp ||\n Math.max(getNumberPrecision(value), getNumberPrecision(step));\n\n const defaultFormat = (value: string): string => {\n const sanitized = value.trim();\n if (!sanitized.length) {\n return \"\";\n }\n const floatValue = Number.parseFloat(sanitized);\n const updatedValue = Number.isNaN(floatValue)\n ? sanitized\n : floatValue.toFixed(decimalScale);\n return String(updatedValue);\n };\n\n const defaultParse = (value: string) => {\n const sanitizedValue = value.trim();\n if (!sanitizedValue.length) {\n return null;\n }\n if (\n sanitizedValue === \".\" ||\n sanitizedValue === \"+\" ||\n sanitizedValue === \"-\"\n ) {\n return 0;\n }\n const floatString = Number.parseFloat(value).toFixed(decimalScale);\n return Number.parseFloat(floatString);\n };\n\n const format = formatProp ?? defaultFormat;\n const parse = parseProp ?? defaultParse;\n\n // Committed values are complete numbers, created through blur or increment/decrement, not partial entries such as \"0.\" created by input/onChange.\n const lastCommitValue = useRef<string>(value);\n const commit = (\n event: SyntheticEvent | null,\n newNumber: number | null,\n newInputValue: string,\n ) => {\n let safeNumber = newNumber;\n if (safeNumber !== null && !Number.isNaN(safeNumber)) {\n safeNumber = Math.max(\n Number.MIN_SAFE_INTEGER,\n Math.min(Number.MAX_SAFE_INTEGER, safeNumber),\n );\n if (clamp) {\n safeNumber = Math.max(min, Math.min(max, safeNumber));\n }\n }\n const commitValue =\n safeNumber !== null && !Number.isNaN(safeNumber)\n ? safeNumber.toFixed(decimalScale)\n : newInputValue;\n\n if (commitValue !== value) {\n setValue(commitValue);\n }\n\n if (lastCommitValue.current !== commitValue) {\n onChange?.(event, commitValue);\n onNumberChangeProp?.(event, safeNumber);\n }\n lastCommitValue.current = commitValue;\n };\n\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n onBlur?.(event);\n };\n\n const handleInputBlur = (event: FocusEvent<HTMLInputElement>) => {\n setIsEditing(false);\n inputOnBlur?.(event);\n const parsedValue = parse(value);\n commit(event, parsedValue, value);\n };\n\n const handleInputFocus = (event: FocusEvent<HTMLInputElement>) => {\n setIsEditing(false);\n inputOnFocus?.(event);\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n const inputValue = event.currentTarget.value;\n\n if (!inputValue.length) {\n setValue(\"\");\n onChange?.(event, \"\");\n return;\n }\n const validValue = pattern ? pattern(inputValue) : true;\n\n if (validValue) {\n setIsEditing(true);\n onChange?.(event, event.target.value);\n setValue(inputValue);\n } else {\n event.preventDefault();\n }\n };\n\n const decrementValue = (event?: SyntheticEvent, block?: boolean) => {\n const decrementStep = (block ? stepMultiplier : 1) * step;\n let adjustedValue = parse(value) ?? 0;\n if (Number.isNaN(adjustedValue)) {\n return;\n }\n adjustedValue -= decrementStep;\n commit(event ?? null, adjustedValue, String(adjustedValue));\n };\n\n let floatValue = parse(value) ?? 0;\n floatValue = Math.max(\n Number.MIN_SAFE_INTEGER,\n Math.min(Number.MAX_SAFE_INTEGER, floatValue),\n );\n if (clamp) {\n floatValue = Math.max(min, Math.min(max, floatValue));\n }\n\n const { activate: activateDecrement } = useActivateWhileMouseDown(\n decrementValue,\n floatValue <= min,\n );\n\n const incrementValue = (event?: SyntheticEvent, block?: boolean) => {\n const incrementStep = (block ? stepMultiplier : 1) * step;\n let adjustedValue = parse(value) ?? 0;\n if (Number.isNaN(adjustedValue)) {\n return;\n }\n adjustedValue += incrementStep;\n commit(event ?? null, adjustedValue, String(adjustedValue));\n };\n\n useEffect(() => {\n if (isFocused) {\n inputRef.current?.focus();\n }\n }, [isFocused]);\n\n const { activate: activateIncrement } = useActivateWhileMouseDown(\n incrementValue,\n floatValue >= max,\n );\n\n const handleInputKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n switch (event.key) {\n case \"ArrowUp\": {\n event.preventDefault();\n const block = event.shiftKey;\n incrementValue(event, block);\n break;\n }\n case \"ArrowDown\": {\n event.preventDefault();\n const block = event.shiftKey;\n decrementValue(event, block);\n break;\n }\n case \"Home\": {\n event.preventDefault();\n const newValue = String(min);\n setValue(newValue);\n commit(event, min, newValue);\n break;\n }\n case \"End\": {\n event.preventDefault();\n const newValue = String(max);\n setValue(newValue);\n commit(event, max, newValue);\n break;\n }\n case \"PageUp\": {\n event.preventDefault();\n incrementValue(event, true);\n break;\n }\n case \"PageDown\": {\n event.preventDefault();\n decrementValue(event, true);\n break;\n }\n }\n inputOnKeyDown?.(event);\n };\n\n const handleIncrementMouseDown = (\n event: SyntheticEvent,\n disableIncrement: boolean,\n ) => {\n event.preventDefault();\n if (!disableIncrement) {\n setIsEditing(false);\n activateIncrement(event);\n } else if (inputRef.current) {\n inputRef.current.select();\n }\n };\n\n const handleDecrementMouseDown = (\n event: SyntheticEvent,\n disableDecrement: boolean,\n ) => {\n event.preventDefault();\n if (!disableDecrement) {\n setIsEditing(false);\n activateDecrement(event);\n } else if (inputRef.current) {\n inputRef.current.select();\n }\n };\n\n const handleContainerMouseUp: MouseEventHandler<HTMLDivElement> = (\n event,\n ) => {\n setIsFocused(true);\n onMouseUp?.(event);\n };\n\n let renderedValue: string;\n if (isEditing) {\n renderedValue = value;\n } else if (!value?.length) {\n renderedValue = \"\";\n } else {\n renderedValue = format(\n Number.isNaN(floatValue) ? value : String(floatValue),\n );\n }\n\n const disableDecrement = disabled || floatValue - step < min;\n const disableIncrement = disabled || floatValue + step > max;\n return (\n <div\n className={clsx(\n withBaseName(),\n withBaseName(variant),\n {\n [withBaseName(\"focused\")]: isFocused,\n [withBaseName(\"disabled\")]: isDisabled,\n [withBaseName(\"readOnly\")]: isReadOnly,\n [withBaseName(\"hiddenButtons\")]: hideButtons,\n [withBaseName(validationStatus || \"\")]: validationStatus,\n [withBaseName(\"bordered\")]: bordered,\n },\n classNameProp,\n )}\n onBlur={handleBlur}\n onMouseUp={handleContainerMouseUp}\n {...restProps}\n ref={ref}\n >\n {startAdornment && (\n <div className={withBaseName(\"startAdornmentContainer\")}>\n {startAdornment}\n </div>\n )}\n <input\n aria-describedby={\n clsx(formFieldDescribedBy, inputDescribedBy) || undefined\n }\n aria-labelledby={\n clsx(formFieldLabelledBy, inputLabelledBy) || undefined\n }\n aria-invalid={\n !isReadOnly && renderedValue.length\n ? isOutOfRange(floatValue, min, max) ||\n validationStatus === \"error\"\n : undefined\n }\n className={clsx(\n withBaseName(\"input\"),\n withBaseName(`inputTextAlign${capitalize(textAlign)}`),\n inputClassName,\n )}\n disabled={isDisabled}\n onBlur={handleInputBlur}\n onChange={handleInputChange}\n onFocus={handleInputFocus}\n onKeyDown={isReadOnly ? undefined : handleInputKeyDown}\n placeholder={placeholder}\n readOnly={isReadOnly}\n aria-readonly={isReadOnly ? \"true\" : undefined}\n ref={handleInputRef}\n required={isRequired}\n aria-valuemax={!isReadOnly && renderedValue.length ? max : undefined}\n aria-valuemin={!isReadOnly && renderedValue.length ? min : undefined}\n aria-valuenow={!isReadOnly ? floatValue : undefined}\n aria-valuetext={\n !isReadOnly\n ? renderedValue.length\n ? (ariaValueTextProp ?? renderedValue)\n : \"Empty\"\n : undefined\n }\n // Workaround to have readonly conveyed by screen readers (https://github.com/jpmorganchase/salt-ds/issues/4586)\n role={isReadOnly ? \"textbox\" : \"spinbutton\"}\n tabIndex={isDisabled ? -1 : 0}\n value={\n isReadOnly && renderedValue.length === 0\n ? emptyReadOnlyMarker\n : renderedValue\n }\n {...restInputProps}\n />\n <div className={withBaseName(\"activationIndicator\")} />\n {!isDisabled && validationStatus && (\n <StatusAdornment status={validationStatus} id={validationStatusId} />\n )}\n {endAdornment && (\n <div className={withBaseName(\"endAdornmentContainer\")}>\n {endAdornment}\n </div>\n )}\n {!isReadOnly && (\n <div className={clsx(withBaseName(\"buttonContainer\"))}>\n <Button\n aria-hidden={true}\n appearance=\"transparent\"\n tabIndex={-1}\n disabled={disableIncrement}\n className={withBaseName(\"increment\")}\n onMouseDown={(event) =>\n handleIncrementMouseDown(event, disableIncrement)\n }\n >\n <IncreaseIcon aria-hidden />\n </Button>\n <Button\n aria-hidden={true}\n appearance=\"transparent\"\n tabIndex={-1}\n disabled={disableDecrement}\n className={withBaseName(\"decrement\")}\n onMouseDown={(event) =>\n handleDecrementMouseDown(event, disableDecrement)\n }\n >\n <DecreaseIcon aria-hidden />\n </Button>\n </div>\n )}\n </div>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","NumberInput","useWindow","useComponentCssInjection","numberInputCss","useFormFieldProps","useId","useRef","useForkRef","useState","useIcon","useControlled","value","floatValue","useActivateWhileMouseDown","useEffect","disableIncrement","disableDecrement","jsxs","clsx","jsx","capitalize","StatusAdornment","Button"],"mappings":";;;;;;;;;;;AAiCA,MAAM,YAAA,GAAeA,kBAAa,iBAAiB,CAAA;AA0I5C,MAAM,YAAA,GAAe,CAC1B,KAAA,EACA,GAAA,EACA,GAAA,KACG;AACH,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAM,MAAA,EAAQ;AAC9C,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,aACJ,OAAO,KAAA,KAAU,WAAW,MAAA,CAAO,UAAA,CAAW,KAAK,CAAA,GAAI,KAAA;AACzD,EAAA,OAAO,OAAO,KAAA,CAAM,UAAU,CAAA,IAAK,UAAA,GAAa,OAAO,UAAA,GAAa,GAAA;AACtE;AAEA,SAAS,mBAAmB,GAAA,EAAsB;AAChD,EAAA,MAAM,MAAA,GAAS,OAAO,GAAG,CAAA;AAEzB,EAAA,IAAI,OAAO,QAAA,CAAS,GAAG,KAAK,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG;AAChD,IAAA,MAAM,CAAC,IAAA,EAAM,QAAQ,CAAA,GAAI,MAAA,CAAO,MAAM,MAAM,CAAA;AAC5C,IAAA,MAAM,cAAc,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA;AAC1C,IAAA,MAAM,YAAY,WAAA,CAAY,MAAA,GAAS,MAAA,CAAO,QAAA,CAAS,UAAU,EAAE,CAAA;AACnE,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,SAAS,CAAA;AAAA,EAC9B;AAEA,EAAA,IAAI,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG;AACxB,IAAA,OAAO,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,CAAE,MAAA;AAAA,EAC9B;AAEA,EAAA,OAAO,CAAA;AACT;AAEA,MAAM,cAAA,GAA8C,CAAC,UAAA,KACnD,6BAAA,CAA8B,KAAK,UAAU,CAAA;AAExC,MAAM,WAAA,GAAcC,gBAAA;AAAA,EACzB,SAASC,YAAAA,CACP;AAAA,IACE,gBAAA,EAAkB,iBAAA;AAAA,IAClB,QAAA;AAAA,IACA,SAAA,EAAW,aAAA;AAAA,IACX,KAAA;AAAA,IACA,YAAA,EAAc,gBAAA;AAAA,IACd,QAAA;AAAA,IACA,mBAAA,GAAsB,QAAA;AAAA,IACtB,YAAA;AAAA,IACA,MAAA,EAAQ,UAAA;AAAA,IACR,WAAA;AAAA,IACA,EAAA,EAAI,MAAA;AAAA,IACJ,OAAA,GAAU,cAAA;AAAA,IACV,UAAA,EAAY,iBAAiB,EAAC;AAAA,IAC9B,QAAA,EAAU,YAAA;AAAA,IACV,MAAM,MAAA,CAAO,gBAAA;AAAA,IACb,MAAM,MAAA,CAAO,gBAAA;AAAA,IACb,MAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,cAAA,EAAgB,kBAAA;AAAA,IAChB,KAAA,EAAO,SAAA;AAAA,IACP,WAAA;AAAA,IACA,QAAA,EAAU,YAAA;AAAA,IACV,cAAA;AAAA,IACA,IAAA,GAAO,CAAA;AAAA,IACP,cAAA,GAAiB,CAAA;AAAA,IACjB,SAAA,GAAY,MAAA;AAAA,IACZ,gBAAA,EAAkB,oBAAA;AAAA,IAClB,KAAA,EAAO,SAAA;AAAA,IACP,OAAA,GAAU,SAAA;AAAA,IACV,YAAA,EAAc,gBAAA;AAAA,IACd,GAAG;AAAA,KAEL,GAAA,EACA;AACA,IAAA,MAAM,eAAeC,gBAAA,EAAU;AAC/B,IAAAC,+BAAA,CAAyB;AAAA,MACvB,MAAA,EAAQ,mBAAA;AAAA,MACR,GAAA,EAAKC,aAAA;AAAA,MACL,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,MAAM;AAAA,MACJ,SAAA,EAAW;AAAA,QACT,kBAAA,EAAoB,oBAAA;AAAA,QACpB,iBAAA,EAAmB;AAAA,UACjB,EAAC;AAAA,MACL,QAAA,EAAU,iBAAA;AAAA,MACV,QAAA,EAAU,iBAAA;AAAA,MACV,SAAA,EAAW,iBAAA;AAAA,MACX,gBAAA,EAAkB;AAAA,QAChBC,sBAAA,EAAkB;AAEtB,IAAA,MAAM,aAAa,QAAA,IAAY,iBAAA;AAC/B,IAAA,MAAM,aAAa,YAAA,IAAgB,iBAAA;AACnC,IAAA,MAAM,mBAAmB,yBAAA,IAA6B,oBAAA;AACtD,IAAA,MAAM,kBAAA,GAAqBC,WAAM,MAAM,CAAA;AACvC,IAAA,MAAM,QAAA,GAAWC,aAAyB,IAAI,CAAA;AAC9C,IAAA,MAAM,cAAA,GAAiBC,eAAA,CAAW,YAAA,EAAc,QAAQ,CAAA;AAExD,IAAA,MAAM;AAAA,MACJ,kBAAA,EAAoB,gBAAA;AAAA,MACpB,iBAAA,EAAmB,eAAA;AAAA,MACnB,SAAA,EAAW,cAAA;AAAA,MACX,MAAA,EAAQ,WAAA;AAAA,MACR,OAAA,EAAS,YAAA;AAAA,MACT,QAAA,EAAU,aAAA;AAAA,MACV,SAAA,EAAW,cAAA;AAAA,MACX,GAAG;AAAA,KACL,GAAI,cAAA;AAEJ,IAAA,MAAM,UAAA,GAAa,oBACf,CAAC,UAAA,EAAY,UAAU,CAAA,CAAE,QAAA,CAAS,iBAAiB,CAAA,GACnD,aAAA;AAEJ,IAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIC,eAAS,KAAK,CAAA;AAChD,IAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,eAAS,KAAK,CAAA;AAChD,IAAA,MAAM,EAAE,YAAA,EAAc,YAAA,EAAa,GAAIC,YAAA,EAAQ;AAE/C,IAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIC,kBAAA,CAAc;AAAA,MACtC,UAAA,EAAY,SAAA,KAAc,MAAA,GAAY,MAAA,CAAO,SAAS,CAAA,GAAI,MAAA;AAAA,MAC1D,OAAA,EAAS,MAAA,CAAO,gBAAA,IAAoB,EAAE,CAAA;AAAA,MACtC,IAAA,EAAM,aAAA;AAAA,MACN,KAAA,EAAO;AAAA,KACR,CAAA;AAED,IAAA,MAAM,YAAA,GACJ,oBACA,IAAA,CAAK,GAAA,CAAI,mBAAmB,KAAK,CAAA,EAAG,kBAAA,CAAmB,IAAI,CAAC,CAAA;AAE9D,IAAA,MAAM,aAAA,GAAgB,CAACC,MAAAA,KAA0B;AAC/C,MAAA,MAAM,SAAA,GAAYA,OAAM,IAAA,EAAK;AAC7B,MAAA,IAAI,CAAC,UAAU,MAAA,EAAQ;AACrB,QAAA,OAAO,EAAA;AAAA,MACT;AACA,MAAA,MAAMC,WAAAA,GAAa,MAAA,CAAO,UAAA,CAAW,SAAS,CAAA;AAC9C,MAAA,MAAM,YAAA,GAAe,OAAO,KAAA,CAAMA,WAAU,IACxC,SAAA,GACAA,WAAAA,CAAW,QAAQ,YAAY,CAAA;AACnC,MAAA,OAAO,OAAO,YAAY,CAAA;AAAA,IAC5B,CAAA;AAEA,IAAA,MAAM,YAAA,GAAe,CAACD,MAAAA,KAAkB;AACtC,MAAA,MAAM,cAAA,GAAiBA,OAAM,IAAA,EAAK;AAClC,MAAA,IAAI,CAAC,eAAe,MAAA,EAAQ;AAC1B,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,IACE,cAAA,KAAmB,GAAA,IACnB,cAAA,KAAmB,GAAA,IACnB,mBAAmB,GAAA,EACnB;AACA,QAAA,OAAO,CAAA;AAAA,MACT;AACA,MAAA,MAAM,cAAc,MAAA,CAAO,UAAA,CAAWA,MAAK,CAAA,CAAE,QAAQ,YAAY,CAAA;AACjE,MAAA,OAAO,MAAA,CAAO,WAAW,WAAW,CAAA;AAAA,IACtC,CAAA;AAEA,IAAA,MAAM,SAAS,UAAA,IAAc,aAAA;AAC7B,IAAA,MAAM,QAAQ,SAAA,IAAa,YAAA;AAG3B,IAAA,MAAM,eAAA,GAAkBL,aAAe,KAAK,CAAA;AAC5C,IAAA,MAAM,MAAA,GAAS,CACb,KAAA,EACA,SAAA,EACA,aAAA,KACG;AACH,MAAA,IAAI,UAAA,GAAa,SAAA;AACjB,MAAA,IAAI,eAAe,IAAA,IAAQ,CAAC,MAAA,CAAO,KAAA,CAAM,UAAU,CAAA,EAAG;AACpD,QAAA,UAAA,GAAa,IAAA,CAAK,GAAA;AAAA,UAChB,MAAA,CAAO,gBAAA;AAAA,UACP,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,gBAAA,EAAkB,UAAU;AAAA,SAC9C;AACA,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,UAAA,GAAa,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA,EAAK,UAAU,CAAC,CAAA;AAAA,QACtD;AAAA,MACF;AACA,MAAA,MAAM,WAAA,GACJ,UAAA,KAAe,IAAA,IAAQ,CAAC,MAAA,CAAO,KAAA,CAAM,UAAU,CAAA,GAC3C,UAAA,CAAW,OAAA,CAAQ,YAAY,CAAA,GAC/B,aAAA;AAEN,MAAA,IAAI,gBAAgB,KAAA,EAAO;AACzB,QAAA,QAAA,CAAS,WAAW,CAAA;AAAA,MACtB;AAEA,MAAA,IAAI,eAAA,CAAgB,YAAY,WAAA,EAAa;AAC3C,QAAA,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAW,KAAA,EAAO,WAAA,CAAA;AAClB,QAAA,kBAAA,IAAA,IAAA,GAAA,MAAA,GAAA,kBAAA,CAAqB,KAAA,EAAO,UAAA,CAAA;AAAA,MAC9B;AACA,MAAA,eAAA,CAAgB,OAAA,GAAU,WAAA;AAAA,IAC5B,CAAA;AAEA,IAAA,MAAM,UAAA,GAAa,CAAC,KAAA,KAAwC;AAC1D,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,MAAA,IAAA,IAAA,GAAA,MAAA,GAAA,MAAA,CAAS,KAAA,CAAA;AAAA,IACX,CAAA;AAEA,IAAA,MAAM,eAAA,GAAkB,CAAC,KAAA,KAAwC;AAC/D,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,WAAA,IAAA,IAAA,GAAA,MAAA,GAAA,WAAA,CAAc,KAAA,CAAA;AACd,MAAA,MAAM,WAAA,GAAc,MAAM,KAAK,CAAA;AAC/B,MAAA,MAAA,CAAO,KAAA,EAAO,aAAa,KAAK,CAAA;AAAA,IAClC,CAAA;AAEA,IAAA,MAAM,gBAAA,GAAmB,CAAC,KAAA,KAAwC;AAChE,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAe,KAAA,CAAA;AAAA,IACjB,CAAA;AAEA,IAAA,MAAM,iBAAA,GAAoB,CAAC,KAAA,KAAyC;AAClE,MAAA,MAAM,UAAA,GAAa,MAAM,aAAA,CAAc,KAAA;AAEvC,MAAA,IAAI,CAAC,WAAW,MAAA,EAAQ;AACtB,QAAA,QAAA,CAAS,EAAE,CAAA;AACX,QAAA,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAW,KAAA,EAAO,EAAA,CAAA;AAClB,QAAA;AAAA,MACF;AACA,MAAA,MAAM,UAAA,GAAa,OAAA,GAAU,OAAA,CAAQ,UAAU,CAAA,GAAI,IAAA;AAEnD,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,YAAA,CAAa,IAAI,CAAA;AACjB,QAAA,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAW,KAAA,EAAO,MAAM,MAAA,CAAO,KAAA,CAAA;AAC/B,QAAA,QAAA,CAAS,UAAU,CAAA;AAAA,MACrB,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,cAAA,EAAe;AAAA,MACvB;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,cAAA,GAAiB,CAAC,KAAA,EAAwB,KAAA,KAAoB;AAClE,MAAA,MAAM,aAAA,GAAA,CAAiB,KAAA,GAAQ,cAAA,GAAiB,CAAA,IAAK,IAAA;AACrD,MAAA,IAAI,aAAA,GAAgB,KAAA,CAAM,KAAK,CAAA,IAAK,CAAA;AACpC,MAAA,IAAI,MAAA,CAAO,KAAA,CAAM,aAAa,CAAA,EAAG;AAC/B,QAAA;AAAA,MACF;AACA,MAAA,aAAA,IAAiB,aAAA;AACjB,MAAA,MAAA,CAAO,KAAA,IAAS,IAAA,EAAM,aAAA,EAAe,MAAA,CAAO,aAAa,CAAC,CAAA;AAAA,IAC5D,CAAA;AAEA,IAAA,IAAI,UAAA,GAAa,KAAA,CAAM,KAAK,CAAA,IAAK,CAAA;AACjC,IAAA,UAAA,GAAa,IAAA,CAAK,GAAA;AAAA,MAChB,MAAA,CAAO,gBAAA;AAAA,MACP,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,gBAAA,EAAkB,UAAU;AAAA,KAC9C;AACA,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,UAAA,GAAa,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA,EAAK,UAAU,CAAC,CAAA;AAAA,IACtD;AAEA,IAAA,MAAM,EAAE,QAAA,EAAU,iBAAA,EAAkB,GAAIO,mDAAA;AAAA,MACtC,cAAA;AAAA,MACA,UAAA,IAAc;AAAA,KAChB;AAEA,IAAA,MAAM,cAAA,GAAiB,CAAC,KAAA,EAAwB,KAAA,KAAoB;AAClE,MAAA,MAAM,aAAA,GAAA,CAAiB,KAAA,GAAQ,cAAA,GAAiB,CAAA,IAAK,IAAA;AACrD,MAAA,IAAI,aAAA,GAAgB,KAAA,CAAM,KAAK,CAAA,IAAK,CAAA;AACpC,MAAA,IAAI,MAAA,CAAO,KAAA,CAAM,aAAa,CAAA,EAAG;AAC/B,QAAA;AAAA,MACF;AACA,MAAA,aAAA,IAAiB,aAAA;AACjB,MAAA,MAAA,CAAO,KAAA,IAAS,IAAA,EAAM,aAAA,EAAe,MAAA,CAAO,aAAa,CAAC,CAAA;AAAA,IAC5D,CAAA;AAEA,IAAAC,eAAA,CAAU,MAAM;AA/apB,MAAA,IAAA,EAAA;AAgbM,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,CAAA,EAAA,GAAA,QAAA,CAAS,YAAT,IAAA,GAAA,MAAA,GAAA,EAAA,CAAkB,KAAA,EAAA;AAAA,MACpB;AAAA,IACF,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,IAAA,MAAM,EAAE,QAAA,EAAU,iBAAA,EAAkB,GAAID,mDAAA;AAAA,MACtC,cAAA;AAAA,MACA,UAAA,IAAc;AAAA,KAChB;AAEA,IAAA,MAAM,kBAAA,GAAqB,CAAC,KAAA,KAA2C;AACrE,MAAA,QAAQ,MAAM,GAAA;AAAK,QACjB,KAAK,SAAA,EAAW;AACd,UAAA,KAAA,CAAM,cAAA,EAAe;AACrB,UAAA,MAAM,QAAQ,KAAA,CAAM,QAAA;AACpB,UAAA,cAAA,CAAe,OAAO,KAAK,CAAA;AAC3B,UAAA;AAAA,QACF;AAAA,QACA,KAAK,WAAA,EAAa;AAChB,UAAA,KAAA,CAAM,cAAA,EAAe;AACrB,UAAA,MAAM,QAAQ,KAAA,CAAM,QAAA;AACpB,UAAA,cAAA,CAAe,OAAO,KAAK,CAAA;AAC3B,UAAA;AAAA,QACF;AAAA,QACA,KAAK,MAAA,EAAQ;AACX,UAAA,KAAA,CAAM,cAAA,EAAe;AACrB,UAAA,MAAM,QAAA,GAAW,OAAO,GAAG,CAAA;AAC3B,UAAA,QAAA,CAAS,QAAQ,CAAA;AACjB,UAAA,MAAA,CAAO,KAAA,EAAO,KAAK,QAAQ,CAAA;AAC3B,UAAA;AAAA,QACF;AAAA,QACA,KAAK,KAAA,EAAO;AACV,UAAA,KAAA,CAAM,cAAA,EAAe;AACrB,UAAA,MAAM,QAAA,GAAW,OAAO,GAAG,CAAA;AAC3B,UAAA,QAAA,CAAS,QAAQ,CAAA;AACjB,UAAA,MAAA,CAAO,KAAA,EAAO,KAAK,QAAQ,CAAA;AAC3B,UAAA;AAAA,QACF;AAAA,QACA,KAAK,QAAA,EAAU;AACb,UAAA,KAAA,CAAM,cAAA,EAAe;AACrB,UAAA,cAAA,CAAe,OAAO,IAAI,CAAA;AAC1B,UAAA;AAAA,QACF;AAAA,QACA,KAAK,UAAA,EAAY;AACf,UAAA,KAAA,CAAM,cAAA,EAAe;AACrB,UAAA,cAAA,CAAe,OAAO,IAAI,CAAA;AAC1B,UAAA;AAAA,QACF;AAAA;AAEF,MAAA,cAAA,IAAA,IAAA,GAAA,MAAA,GAAA,cAAA,CAAiB,KAAA,CAAA;AAAA,IACnB,CAAA;AAEA,IAAA,MAAM,wBAAA,GAA2B,CAC/B,KAAA,EACAE,iBAAAA,KACG;AACH,MAAA,KAAA,CAAM,cAAA,EAAe;AACrB,MAAA,IAAI,CAACA,iBAAAA,EAAkB;AACrB,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,iBAAA,CAAkB,KAAK,CAAA;AAAA,MACzB,CAAA,MAAA,IAAW,SAAS,OAAA,EAAS;AAC3B,QAAA,QAAA,CAAS,QAAQ,MAAA,EAAO;AAAA,MAC1B;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,wBAAA,GAA2B,CAC/B,KAAA,EACAC,iBAAAA,KACG;AACH,MAAA,KAAA,CAAM,cAAA,EAAe;AACrB,MAAA,IAAI,CAACA,iBAAAA,EAAkB;AACrB,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,iBAAA,CAAkB,KAAK,CAAA;AAAA,MACzB,CAAA,MAAA,IAAW,SAAS,OAAA,EAAS;AAC3B,QAAA,QAAA,CAAS,QAAQ,MAAA,EAAO;AAAA,MAC1B;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,sBAAA,GAA4D,CAChE,KAAA,KACG;AACH,MAAA,YAAA,CAAa,IAAI,CAAA;AACjB,MAAA,SAAA,IAAA,IAAA,GAAA,MAAA,GAAA,SAAA,CAAY,KAAA,CAAA;AAAA,IACd,CAAA;AAEA,IAAA,IAAI,aAAA;AACJ,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,aAAA,GAAgB,KAAA;AAAA,IAClB,CAAA,MAAA,IAAW,EAAC,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAO,MAAA,CAAA,EAAQ;AACzB,MAAA,aAAA,GAAgB,EAAA;AAAA,IAClB,CAAA,MAAO;AACL,MAAA,aAAA,GAAgB,MAAA;AAAA,QACd,OAAO,KAAA,CAAM,UAAU,CAAA,GAAI,KAAA,GAAQ,OAAO,UAAU;AAAA,OACtD;AAAA,IACF;AAEA,IAAA,MAAM,gBAAA,GAAmB,QAAA,IAAY,UAAA,GAAa,IAAA,GAAO,GAAA;AACzD,IAAA,MAAM,gBAAA,GAAmB,QAAA,IAAY,UAAA,GAAa,IAAA,GAAO,GAAA;AACzD,IAAA,uBACEC,eAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAWC,SAAA;AAAA,UACT,YAAA,EAAa;AAAA,UACb,aAAa,OAAO,CAAA;AAAA,UACpB;AAAA,YACE,CAAC,YAAA,CAAa,SAAS,CAAC,GAAG,SAAA;AAAA,YAC3B,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG,UAAA;AAAA,YAC5B,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG,UAAA;AAAA,YAC5B,CAAC,YAAA,CAAa,eAAe,CAAC,GAAG,WAAA;AAAA,YACjC,CAAC,YAAA,CAAa,gBAAA,IAAoB,EAAE,CAAC,GAAG,gBAAA;AAAA,YACxC,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG;AAAA,WAC9B;AAAA,UACA;AAAA,SACF;AAAA,QACA,MAAA,EAAQ,UAAA;AAAA,QACR,SAAA,EAAW,sBAAA;AAAA,QACV,GAAG,SAAA;AAAA,QACJ,GAAA;AAAA,QAEC,QAAA,EAAA;AAAA,UAAA,cAAA,mCACE,KAAA,EAAA,EAAI,SAAA,EAAW,YAAA,CAAa,yBAAyB,GACnD,QAAA,EAAA,cAAA,EACH,CAAA;AAAA,0BAEFC,cAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,kBAAA,EACED,SAAA,CAAK,oBAAA,EAAsB,gBAAgB,CAAA,IAAK,MAAA;AAAA,cAElD,iBAAA,EACEA,SAAA,CAAK,mBAAA,EAAqB,eAAe,CAAA,IAAK,MAAA;AAAA,cAEhD,cAAA,EACE,CAAC,UAAA,IAAc,aAAA,CAAc,MAAA,GACzB,YAAA,CAAa,UAAA,EAAY,GAAA,EAAK,GAAG,CAAA,IACjC,gBAAA,KAAqB,OAAA,GACrB,MAAA;AAAA,cAEN,SAAA,EAAWA,SAAA;AAAA,gBACT,aAAa,OAAO,CAAA;AAAA,gBACpB,YAAA,CAAa,CAAA,cAAA,EAAiBE,eAAA,CAAW,SAAS,CAAC,CAAA,CAAE,CAAA;AAAA,gBACrD;AAAA,eACF;AAAA,cACA,QAAA,EAAU,UAAA;AAAA,cACV,MAAA,EAAQ,eAAA;AAAA,cACR,QAAA,EAAU,iBAAA;AAAA,cACV,OAAA,EAAS,gBAAA;AAAA,cACT,SAAA,EAAW,aAAa,MAAA,GAAY,kBAAA;AAAA,cACpC,WAAA;AAAA,cACA,QAAA,EAAU,UAAA;AAAA,cACV,eAAA,EAAe,aAAa,MAAA,GAAS,MAAA;AAAA,cACrC,GAAA,EAAK,cAAA;AAAA,cACL,QAAA,EAAU,UAAA;AAAA,cACV,eAAA,EAAe,CAAC,UAAA,IAAc,aAAA,CAAc,SAAS,GAAA,GAAM,MAAA;AAAA,cAC3D,eAAA,EAAe,CAAC,UAAA,IAAc,aAAA,CAAc,SAAS,GAAA,GAAM,MAAA;AAAA,cAC3D,eAAA,EAAe,CAAC,UAAA,GAAa,UAAA,GAAa,MAAA;AAAA,cAC1C,kBACE,CAAC,UAAA,GACG,cAAc,MAAA,GACX,iBAAA,IAAqB,gBACtB,OAAA,GACF,MAAA;AAAA,cAGN,IAAA,EAAM,aAAa,SAAA,GAAY,YAAA;AAAA,cAC/B,QAAA,EAAU,aAAa,EAAA,GAAK,CAAA;AAAA,cAC5B,KAAA,EACE,UAAA,IAAc,aAAA,CAAc,MAAA,KAAW,IACnC,mBAAA,GACA,aAAA;AAAA,cAEL,GAAG;AAAA;AAAA,WACN;AAAA,0BACAD,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,YAAA,CAAa,qBAAqB,CAAA,EAAG,CAAA;AAAA,UACpD,CAAC,cAAc,gBAAA,oBACdA,cAAA,CAACE,wBAAgB,MAAA,EAAQ,gBAAA,EAAkB,IAAI,kBAAA,EAAoB,CAAA;AAAA,UAEpE,gCACCF,cAAA,CAAC,KAAA,EAAA,EAAI,WAAW,YAAA,CAAa,uBAAuB,GACjD,QAAA,EAAA,YAAA,EACH,CAAA;AAAA,UAED,CAAC,8BACAF,eAAA,CAAC,KAAA,EAAA,EAAI,WAAWC,SAAA,CAAK,YAAA,CAAa,iBAAiB,CAAC,CAAA,EAClD,QAAA,EAAA;AAAA,4BAAAC,cAAA;AAAA,cAACG,WAAA;AAAA,cAAA;AAAA,gBACC,aAAA,EAAa,IAAA;AAAA,gBACb,UAAA,EAAW,aAAA;AAAA,gBACX,QAAA,EAAU,EAAA;AAAA,gBACV,QAAA,EAAU,gBAAA;AAAA,gBACV,SAAA,EAAW,aAAa,WAAW,CAAA;AAAA,gBACnC,WAAA,EAAa,CAAC,KAAA,KACZ,wBAAA,CAAyB,OAAO,gBAAgB,CAAA;AAAA,gBAGlD,QAAA,kBAAAH,cAAA,CAAC,YAAA,EAAA,EAAa,aAAA,EAAW,IAAA,EAAC;AAAA;AAAA,aAC5B;AAAA,4BACAA,cAAA;AAAA,cAACG,WAAA;AAAA,cAAA;AAAA,gBACC,aAAA,EAAa,IAAA;AAAA,gBACb,UAAA,EAAW,aAAA;AAAA,gBACX,QAAA,EAAU,EAAA;AAAA,gBACV,QAAA,EAAU,gBAAA;AAAA,gBACV,SAAA,EAAW,aAAa,WAAW,CAAA;AAAA,gBACnC,WAAA,EAAa,CAAC,KAAA,KACZ,wBAAA,CAAyB,OAAO,gBAAgB,CAAA;AAAA,gBAGlD,QAAA,kBAAAH,cAAA,CAAC,YAAA,EAAA,EAAa,aAAA,EAAW,IAAA,EAAC;AAAA;AAAA;AAC5B,WAAA,EACF;AAAA;AAAA;AAAA,KAEJ;AAAA,EAEJ;AACF;;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var css_248z = ".saltTabNextTrigger {\n all: unset;\n display: flex;\n gap: var(--salt-spacing-100);\n align-items: center;\n justify-content: center;\n flex: 1;\n overflow: hidden;\n}\n\n/* The action should be triggered by clicking anywhere on the tab. */\n.saltTabNextTrigger::before {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n}\n";
|
|
3
|
+
var css_248z = ".saltTabNextTrigger {\n all: unset;\n display: flex;\n gap: var(--salt-spacing-100);\n align-items: center;\n justify-content: center;\n flex: 1;\n overflow: hidden;\n}\n\n/* The action should be triggered by clicking anywhere on the tab. */\n.saltTabNextTrigger::before {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n}\n\n.saltTabNextTrigger:focus-visible {\n outline: none;\n}\n";
|
|
4
4
|
|
|
5
5
|
module.exports = css_248z;
|
|
6
6
|
//# sourceMappingURL=TabNextTrigger.css.js.map
|
|
@@ -18,7 +18,8 @@ function useCalendarDay(props) {
|
|
|
18
18
|
setHoveredDate,
|
|
19
19
|
isDayUnselectable,
|
|
20
20
|
isDayHighlighted,
|
|
21
|
-
isOutsideAllowedMonths
|
|
21
|
+
isOutsideAllowedMonths,
|
|
22
|
+
isOutsideAllowedDates
|
|
22
23
|
}
|
|
23
24
|
} = useCalendarContext();
|
|
24
25
|
const selectionManager = useCalendarSelectionDay({ date });
|
|
@@ -52,7 +53,7 @@ function useCalendarDay(props) {
|
|
|
52
53
|
const unselectableReason = isDayUnselectable(date);
|
|
53
54
|
const highlightedReason = isDayHighlighted(date);
|
|
54
55
|
const outOfRange = !dateAdapter.isSame(date, month, "month");
|
|
55
|
-
const unselectable = Boolean(unselectableReason) || isOutsideAllowedMonths(date);
|
|
56
|
+
const unselectable = Boolean(unselectableReason) || isOutsideAllowedMonths(date) || isOutsideAllowedDates(date);
|
|
56
57
|
const highlighted = Boolean(highlightedReason);
|
|
57
58
|
const hidden = hideOutOfRangeDates ? outOfRange : false;
|
|
58
59
|
return {
|