@codefast/ui 0.3.11 → 0.3.12-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +4 -0
- package/dist/components/accordion.d.ts +11 -29
- package/dist/components/accordion.d.ts.map +1 -0
- package/dist/components/accordion.js +10 -37
- package/dist/components/alert-dialog.d.ts +25 -60
- package/dist/components/alert-dialog.d.ts.map +1 -0
- package/dist/components/alert-dialog.js +16 -69
- package/dist/components/alert.d.ts +16 -27
- package/dist/components/alert.d.ts.map +1 -0
- package/dist/components/alert.js +22 -30
- package/dist/components/aspect-ratio.d.ts +5 -8
- package/dist/components/aspect-ratio.d.ts.map +1 -0
- package/dist/components/aspect-ratio.js +5 -7
- package/dist/components/avatar.d.ts +7 -17
- package/dist/components/avatar.d.ts.map +1 -0
- package/dist/components/avatar.js +7 -18
- package/dist/components/badge.d.ts +15 -21
- package/dist/components/badge.d.ts.map +1 -0
- package/dist/components/badge.js +23 -20
- package/dist/components/breadcrumb.d.ts +13 -35
- package/dist/components/breadcrumb.d.ts.map +1 -0
- package/dist/components/breadcrumb.js +13 -49
- package/dist/components/button-group.d.ts +15 -29
- package/dist/components/button-group.d.ts.map +1 -0
- package/dist/components/button-group.js +22 -27
- package/dist/components/button.d.ts +26 -35
- package/dist/components/button.d.ts.map +1 -0
- package/dist/components/button.js +43 -51
- package/dist/components/calendar.d.ts +10 -24
- package/dist/components/calendar.d.ts.map +1 -0
- package/dist/components/calendar.js +75 -92
- package/dist/components/card.d.ts +11 -34
- package/dist/components/card.d.ts.map +1 -0
- package/dist/components/card.js +11 -39
- package/dist/components/carousel.d.ts +25 -55
- package/dist/components/carousel.d.ts.map +1 -0
- package/dist/components/carousel.js +82 -114
- package/dist/components/chart.d.ts +37 -72
- package/dist/components/chart.d.ts.map +1 -0
- package/dist/components/chart.js +161 -150
- package/dist/components/checkbox-cards.d.ts +9 -15
- package/dist/components/checkbox-cards.d.ts.map +1 -0
- package/dist/components/checkbox-cards.js +8 -22
- package/dist/components/checkbox-group.d.ts +9 -16
- package/dist/components/checkbox-group.d.ts.map +1 -0
- package/dist/components/checkbox-group.js +7 -19
- package/dist/components/checkbox.d.ts +5 -9
- package/dist/components/checkbox.d.ts.map +1 -0
- package/dist/components/checkbox.js +6 -14
- package/dist/components/collapsible.d.ts +7 -14
- package/dist/components/collapsible.d.ts.map +1 -0
- package/dist/components/collapsible.js +7 -15
- package/dist/components/command.d.ts +24 -55
- package/dist/components/command.d.ts.map +1 -0
- package/dist/components/command.js +18 -69
- package/dist/components/context-menu.d.ts +23 -72
- package/dist/components/context-menu.d.ts.map +1 -0
- package/dist/components/context-menu.js +21 -89
- package/dist/components/dialog.d.ts +23 -53
- package/dist/components/dialog.d.ts.map +1 -0
- package/dist/components/dialog.js +20 -72
- package/dist/components/drawer.d.ts +29 -60
- package/dist/components/drawer.d.ts.map +1 -0
- package/dist/components/drawer.js +16 -58
- package/dist/components/dropdown-menu.d.ts +23 -73
- package/dist/components/dropdown-menu.d.ts.map +1 -0
- package/dist/components/dropdown-menu.js +21 -96
- package/dist/components/empty.d.ts +16 -37
- package/dist/components/empty.d.ts.map +1 -0
- package/dist/components/empty.js +24 -44
- package/dist/components/field.d.ts +26 -63
- package/dist/components/field.d.ts.map +1 -0
- package/dist/components/field.js +46 -89
- package/dist/components/form.d.ts +16 -37
- package/dist/components/form.d.ts.map +1 -0
- package/dist/components/form.js +50 -66
- package/dist/components/hover-card.d.ts +8 -21
- package/dist/components/hover-card.d.ts.map +1 -0
- package/dist/components/hover-card.js +8 -23
- package/dist/components/input-group.d.ts +29 -53
- package/dist/components/input-group.d.ts.map +1 -0
- package/dist/components/input-group.js +59 -66
- package/dist/components/input-number.d.ts +8 -28
- package/dist/components/input-number.d.ts.map +1 -0
- package/dist/components/input-number.js +14 -55
- package/dist/components/input-otp.d.ts +11 -24
- package/dist/components/input-otp.d.ts.map +1 -0
- package/dist/components/input-otp.js +13 -34
- package/dist/components/input-password.d.ts +6 -12
- package/dist/components/input-password.d.ts.map +1 -0
- package/dist/components/input-password.js +10 -31
- package/dist/components/input-search.d.ts +9 -18
- package/dist/components/input-search.d.ts.map +1 -0
- package/dist/components/input-search.js +16 -44
- package/dist/components/input.d.ts +5 -10
- package/dist/components/input.d.ts.map +1 -0
- package/dist/components/input.js +5 -9
- package/dist/components/item.d.ts +33 -69
- package/dist/components/item.d.ts.map +1 -0
- package/dist/components/item.js +47 -90
- package/dist/components/kbd.d.ts +6 -13
- package/dist/components/kbd.d.ts.map +1 -0
- package/dist/components/kbd.js +6 -13
- package/dist/components/label.d.ts +5 -9
- package/dist/components/label.d.ts.map +1 -0
- package/dist/components/label.js +5 -8
- package/dist/components/menubar.d.ts +24 -80
- package/dist/components/menubar.d.ts.map +1 -0
- package/dist/components/menubar.js +23 -99
- package/dist/components/native-select.d.ts +7 -16
- package/dist/components/native-select.d.ts.map +1 -0
- package/dist/components/native-select.js +7 -25
- package/dist/components/navigation-menu.d.ts +13 -36
- package/dist/components/navigation-menu.d.ts.map +1 -0
- package/dist/components/navigation-menu.js +25 -61
- package/dist/components/pagination.d.ts +15 -35
- package/dist/components/pagination.d.ts.map +1 -0
- package/dist/components/pagination.js +13 -55
- package/dist/components/popover.d.ts +9 -24
- package/dist/components/popover.d.ts.map +1 -0
- package/dist/components/popover.js +9 -27
- package/dist/components/progress-circle.d.ts +89 -106
- package/dist/components/progress-circle.d.ts.map +1 -0
- package/dist/components/progress-circle.js +70 -103
- package/dist/components/progress.d.ts +5 -10
- package/dist/components/progress.d.ts.map +1 -0
- package/dist/components/progress.js +7 -13
- package/dist/components/radio-cards.d.ts +5 -10
- package/dist/components/radio-cards.d.ts.map +1 -0
- package/dist/components/radio-cards.js +7 -21
- package/dist/components/radio-group.d.ts +6 -13
- package/dist/components/radio-group.d.ts.map +1 -0
- package/dist/components/radio-group.js +6 -17
- package/dist/components/radio.d.ts +6 -12
- package/dist/components/radio.d.ts.map +1 -0
- package/dist/components/radio.js +5 -10
- package/dist/components/resizable.d.ts +8 -18
- package/dist/components/resizable.d.ts.map +1 -0
- package/dist/components/resizable.js +7 -21
- package/dist/components/scroll-area.d.ts +21 -33
- package/dist/components/scroll-area.d.ts.map +1 -0
- package/dist/components/scroll-area.js +64 -84
- package/dist/components/select.d.ts +17 -50
- package/dist/components/select.d.ts.map +1 -0
- package/dist/components/select.js +26 -78
- package/dist/components/separator.d.ts +20 -29
- package/dist/components/separator.d.ts.map +1 -0
- package/dist/components/separator.js +27 -36
- package/dist/components/sheet.d.ts +30 -62
- package/dist/components/sheet.d.ts.map +1 -0
- package/dist/components/sheet.js +36 -80
- package/dist/components/sidebar.d.ts +67 -160
- package/dist/components/sidebar.d.ts.map +1 -0
- package/dist/components/sidebar.js +166 -301
- package/dist/components/skeleton.d.ts +5 -9
- package/dist/components/skeleton.d.ts.map +1 -0
- package/dist/components/skeleton.js +5 -8
- package/dist/components/slider.d.ts +5 -13
- package/dist/components/slider.d.ts.map +1 -0
- package/dist/components/slider.js +12 -34
- package/dist/components/sonner.d.ts +8 -10
- package/dist/components/sonner.d.ts.map +1 -0
- package/dist/components/sonner.js +13 -16
- package/dist/components/spinner.d.ts +6 -12
- package/dist/components/spinner.d.ts.map +1 -0
- package/dist/components/spinner.js +20 -33
- package/dist/components/switch.d.ts +5 -9
- package/dist/components/switch.d.ts.map +1 -0
- package/dist/components/switch.js +5 -12
- package/dist/components/table.d.ts +12 -37
- package/dist/components/table.d.ts.map +1 -0
- package/dist/components/table.js +12 -47
- package/dist/components/tabs.d.ts +8 -21
- package/dist/components/tabs.d.ts.map +1 -0
- package/dist/components/tabs.js +8 -23
- package/dist/components/textarea.d.ts +5 -9
- package/dist/components/textarea.d.ts.map +1 -0
- package/dist/components/textarea.js +5 -8
- package/dist/components/toggle-group.d.ts +10 -24
- package/dist/components/toggle-group.d.ts.map +1 -0
- package/dist/components/toggle-group.js +20 -38
- package/dist/components/toggle.d.ts +18 -25
- package/dist/components/toggle.d.ts.map +1 -0
- package/dist/components/toggle.js +24 -29
- package/dist/components/tooltip.d.ts +9 -24
- package/dist/components/tooltip.d.ts.map +1 -0
- package/dist/components/tooltip.js +9 -28
- package/dist/hooks/use-animated-value.d.ts +2 -4
- package/dist/hooks/use-animated-value.d.ts.map +1 -0
- package/dist/hooks/use-animated-value.js +67 -58
- package/dist/hooks/use-copy-to-clipboard.d.ts +6 -11
- package/dist/hooks/use-copy-to-clipboard.d.ts.map +1 -0
- package/dist/hooks/use-copy-to-clipboard.js +42 -39
- package/dist/hooks/use-is-mobile.d.ts +2 -4
- package/dist/hooks/use-is-mobile.d.ts.map +1 -0
- package/dist/hooks/use-is-mobile.js +20 -23
- package/dist/hooks/use-media-query.d.ts +2 -4
- package/dist/hooks/use-media-query.d.ts.map +1 -0
- package/dist/hooks/use-media-query.js +49 -46
- package/dist/hooks/use-mutation-observer.d.ts +3 -6
- package/dist/hooks/use-mutation-observer.d.ts.map +1 -0
- package/dist/hooks/use-mutation-observer.js +33 -34
- package/dist/hooks/use-pagination.d.ts +15 -22
- package/dist/hooks/use-pagination.d.ts.map +1 -0
- package/dist/hooks/use-pagination.js +99 -99
- package/dist/index.d.ts +131 -69
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +68 -69
- package/dist/primitives/checkbox-group.d.ts +84 -105
- package/dist/primitives/checkbox-group.d.ts.map +1 -0
- package/dist/primitives/checkbox-group.js +91 -105
- package/dist/primitives/input-number.d.ts +41 -51
- package/dist/primitives/input-number.d.ts.map +1 -0
- package/dist/primitives/input-number.js +417 -473
- package/dist/primitives/input.d.ts +43 -48
- package/dist/primitives/input.d.ts.map +1 -0
- package/dist/primitives/input.js +67 -66
- package/dist/primitives/progress-circle.d.ts +49 -79
- package/dist/primitives/progress-circle.d.ts.map +1 -0
- package/dist/primitives/progress-circle.js +134 -149
- package/package.json +17 -10
- package/{dist → src}/css/preset.css +1 -1
- /package/{dist → src}/css/amber.css +0 -0
- /package/{dist → src}/css/blue.css +0 -0
- /package/{dist → src}/css/cyan.css +0 -0
- /package/{dist → src}/css/emerald.css +0 -0
- /package/{dist → src}/css/fuchsia.css +0 -0
- /package/{dist → src}/css/gray.css +0 -0
- /package/{dist → src}/css/green.css +0 -0
- /package/{dist → src}/css/indigo.css +0 -0
- /package/{dist → src}/css/lime.css +0 -0
- /package/{dist → src}/css/neutral.css +0 -0
- /package/{dist → src}/css/orange.css +0 -0
- /package/{dist → src}/css/pink.css +0 -0
- /package/{dist → src}/css/purple.css +0 -0
- /package/{dist → src}/css/red.css +0 -0
- /package/{dist → src}/css/rose.css +0 -0
- /package/{dist → src}/css/sky.css +0 -0
- /package/{dist → src}/css/slate.css +0 -0
- /package/{dist → src}/css/stone.css +0 -0
- /package/{dist → src}/css/style.css +0 -0
- /package/{dist → src}/css/teal.css +0 -0
- /package/{dist → src}/css/violet.css +0 -0
- /package/{dist → src}/css/yellow.css +0 -0
- /package/{dist → src}/css/zinc.css +0 -0
|
@@ -1,514 +1,458 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { composeEventHandlers } from "@radix-ui/primitive";
|
|
4
3
|
import { createContextScope } from "@radix-ui/react-context";
|
|
5
4
|
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
6
|
-
import {
|
|
7
|
-
|
|
5
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
6
|
+
import * as InputPrimitive from "#primitives/input";
|
|
7
|
+
import { createInputScope } from "#primitives/input";
|
|
8
|
+
/* -----------------------------------------------------------------------------
|
|
9
|
+
* Context: InputNumber
|
|
10
|
+
* -------------------------------------------------------------------------- */
|
|
8
11
|
/**
|
|
9
|
-
* The name of the InputNumber component constant.
|
|
10
|
-
*/
|
|
12
|
+
* The name of the InputNumber component constant.
|
|
13
|
+
*/
|
|
11
14
|
const NUMBER_INPUT_NAME = "InputNumber";
|
|
12
|
-
const [createInputNumberContext, createInputNumberScope] = createContextScope(NUMBER_INPUT_NAME, [
|
|
15
|
+
const [createInputNumberContext, createInputNumberScope] = createContextScope(NUMBER_INPUT_NAME, [
|
|
16
|
+
createInputScope,
|
|
17
|
+
]);
|
|
13
18
|
const useInputScope = createInputScope();
|
|
14
19
|
const [InputNumberContextProvider, useInputNumberContext] = createInputNumberContext(NUMBER_INPUT_NAME);
|
|
15
20
|
function InputNumber(numberInputProps) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
]);
|
|
103
|
-
/**
|
|
104
|
-
* Sets the value to the minimum allowed
|
|
105
|
-
*/
|
|
106
|
-
const handleDecrementToMin = useCallback(() => {
|
|
107
|
-
changeNumberValue((number) => min ?? number - step);
|
|
108
|
-
}, [
|
|
109
|
-
changeNumberValue,
|
|
110
|
-
min,
|
|
111
|
-
step
|
|
112
|
-
]);
|
|
113
|
-
return /* @__PURE__ */ jsx(InputNumberContextProvider, {
|
|
114
|
-
ariaDecrementLabel,
|
|
115
|
-
ariaIncrementLabel,
|
|
116
|
-
defaultValue,
|
|
117
|
-
disabled: props.disabled,
|
|
118
|
-
formatOptions,
|
|
119
|
-
formatValue,
|
|
120
|
-
id,
|
|
121
|
-
inputRef,
|
|
122
|
-
max,
|
|
123
|
-
min,
|
|
124
|
-
parseValue,
|
|
125
|
-
readOnly: props.readOnly,
|
|
126
|
-
scope: __scopeInputNumber,
|
|
127
|
-
value,
|
|
128
|
-
onChange: setValue,
|
|
129
|
-
onDecrement: handleDecrement,
|
|
130
|
-
onDecrementToMin: handleDecrementToMin,
|
|
131
|
-
onIncrement: handleIncrement,
|
|
132
|
-
onIncrementToMax: handleIncrementToMax,
|
|
133
|
-
children: /* @__PURE__ */ jsx(Input, {
|
|
134
|
-
...inputScope,
|
|
135
|
-
...props
|
|
136
|
-
})
|
|
137
|
-
});
|
|
21
|
+
const { __scopeInputNumber, ariaDecrementLabel, ariaIncrementLabel, defaultValue, formatOptions = { minimumFractionDigits: 0, style: "decimal" }, id, locale, max, min, onChange, step = 1, value: valueProperty, ...props } = numberInputProps;
|
|
22
|
+
/** Scope for the input component */
|
|
23
|
+
const inputScope = useInputScope(__scopeInputNumber);
|
|
24
|
+
/** Reference to the input element */
|
|
25
|
+
const inputRef = useRef(null);
|
|
26
|
+
/** Controlled or uncontrolled value state */
|
|
27
|
+
const [value, setValue] = useControllableState({
|
|
28
|
+
defaultProp: defaultValue,
|
|
29
|
+
onChange,
|
|
30
|
+
prop: valueProperty,
|
|
31
|
+
});
|
|
32
|
+
/** Separators used for number formatting based on locale */
|
|
33
|
+
const { decimalSeparator, thousandSeparator } = useMemo(() => getNumberFormatSeparators(locale), [locale]);
|
|
34
|
+
/**
|
|
35
|
+
* Formats a number value into a string representation
|
|
36
|
+
* @param inputValue - The number to format
|
|
37
|
+
* @returns A formatted string representation of the number
|
|
38
|
+
*/
|
|
39
|
+
const formatValue = useCallback((inputValue) => {
|
|
40
|
+
if (inputValue === undefined || Number.isNaN(inputValue)) {
|
|
41
|
+
return "";
|
|
42
|
+
}
|
|
43
|
+
return new Intl.NumberFormat(locale, formatOptions).format(inputValue);
|
|
44
|
+
}, [formatOptions, locale]);
|
|
45
|
+
/**
|
|
46
|
+
* Parses a string or number input into a normalized number value
|
|
47
|
+
* @param inputValue - The value to parse
|
|
48
|
+
* @returns The parsed number value, clamped between min and max
|
|
49
|
+
*/
|
|
50
|
+
const parseValue = useCallback((inputValue) => {
|
|
51
|
+
if (typeof inputValue === "number") {
|
|
52
|
+
return clamp(inputValue, min, max);
|
|
53
|
+
}
|
|
54
|
+
if (typeof inputValue !== "string") {
|
|
55
|
+
return Number.NaN;
|
|
56
|
+
}
|
|
57
|
+
const cleanedValue = inputValue.trim().replaceAll(/[^\d.,\-()]/g, "");
|
|
58
|
+
if (cleanedValue === "") {
|
|
59
|
+
return Number.NaN;
|
|
60
|
+
}
|
|
61
|
+
const normalizedValue = normalizeInputValue(cleanedValue, thousandSeparator, decimalSeparator);
|
|
62
|
+
let parsedValue = Number.parseFloat(normalizedValue);
|
|
63
|
+
if (formatOptions.style === "percent") {
|
|
64
|
+
parsedValue /= 100;
|
|
65
|
+
}
|
|
66
|
+
return Number.isNaN(parsedValue) ? 0 : clamp(parsedValue, min, max);
|
|
67
|
+
}, [decimalSeparator, formatOptions.style, max, min, thousandSeparator]);
|
|
68
|
+
/**
|
|
69
|
+
* Changes the current value based on a provided operation
|
|
70
|
+
* @param operation - Function that takes the current value and returns a new value
|
|
71
|
+
*/
|
|
72
|
+
const changeNumberValue = useCallback((operation) => {
|
|
73
|
+
const inputElement = inputRef.current;
|
|
74
|
+
if (!inputElement || props.disabled || props.readOnly) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const currentValue = parseValue(inputElement.value) || 0;
|
|
78
|
+
const newValue = clamp(operation(currentValue), min, max);
|
|
79
|
+
inputElement.value = formatValue(newValue);
|
|
80
|
+
setValue(newValue);
|
|
81
|
+
}, [props.disabled, formatValue, max, min, parseValue, props.readOnly, setValue]);
|
|
82
|
+
/**
|
|
83
|
+
* Increments the current value by the step amount
|
|
84
|
+
*/
|
|
85
|
+
const handleIncrement = useCallback(() => {
|
|
86
|
+
changeNumberValue((number) => number + step);
|
|
87
|
+
}, [changeNumberValue, step]);
|
|
88
|
+
/**
|
|
89
|
+
* Decrements the current value by the step amount
|
|
90
|
+
*/
|
|
91
|
+
const handleDecrement = useCallback(() => {
|
|
92
|
+
changeNumberValue((number) => number - step);
|
|
93
|
+
}, [changeNumberValue, step]);
|
|
94
|
+
/**
|
|
95
|
+
* Sets the value to the maximum allowed
|
|
96
|
+
*/
|
|
97
|
+
const handleIncrementToMax = useCallback(() => {
|
|
98
|
+
changeNumberValue((number) => max ?? number + step);
|
|
99
|
+
}, [changeNumberValue, max, step]);
|
|
100
|
+
/**
|
|
101
|
+
* Sets the value to the minimum allowed
|
|
102
|
+
*/
|
|
103
|
+
const handleDecrementToMin = useCallback(() => {
|
|
104
|
+
changeNumberValue((number) => min ?? number - step);
|
|
105
|
+
}, [changeNumberValue, min, step]);
|
|
106
|
+
return (_jsx(InputNumberContextProvider, { ariaDecrementLabel: ariaDecrementLabel, ariaIncrementLabel: ariaIncrementLabel, defaultValue: defaultValue, disabled: props.disabled, formatOptions: formatOptions, formatValue: formatValue, id: id, inputRef: inputRef, max: max, min: min, parseValue: parseValue, readOnly: props.readOnly, scope: __scopeInputNumber, value: value, onChange: setValue, onDecrement: handleDecrement, onDecrementToMin: handleDecrementToMin, onIncrement: handleIncrement, onIncrementToMax: handleIncrementToMax, children: _jsx(InputPrimitive.Root, { ...inputScope, ...props }) }));
|
|
138
107
|
}
|
|
108
|
+
/* -----------------------------------------------------------------------------
|
|
109
|
+
* Component: InputNumberField
|
|
110
|
+
* -------------------------------------------------------------------------- */
|
|
139
111
|
/**
|
|
140
|
-
* The name of the InputNumberField component constant.
|
|
141
|
-
*/
|
|
112
|
+
* The name of the InputNumberField component constant.
|
|
113
|
+
*/
|
|
142
114
|
const NUMBER_INPUT_FIELD_NAME = "InputNumberField";
|
|
143
115
|
function InputNumberField({ __scopeInputNumber, onBlur, onKeyDown, ...props }) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
defaultValue,
|
|
308
|
-
inputRef,
|
|
309
|
-
onChange,
|
|
310
|
-
parseValue
|
|
311
|
-
]);
|
|
312
|
-
return /* @__PURE__ */ jsx(InputField, {
|
|
313
|
-
ref: inputRef,
|
|
314
|
-
defaultValue: formatValue(value),
|
|
315
|
-
disabled,
|
|
316
|
-
id,
|
|
317
|
-
inputMode: "decimal",
|
|
318
|
-
max,
|
|
319
|
-
min,
|
|
320
|
-
readOnly,
|
|
321
|
-
step,
|
|
322
|
-
onBlur: composeEventHandlers(onBlur, handleBlur),
|
|
323
|
-
onKeyDown: combinedKeyDownHandler,
|
|
324
|
-
...inputScope,
|
|
325
|
-
...props
|
|
326
|
-
});
|
|
116
|
+
// Retrieve input number context and input scope
|
|
117
|
+
const inputScope = useInputScope(__scopeInputNumber);
|
|
118
|
+
const { defaultValue, disabled, formatValue, id, inputRef, max, min, onChange, onDecrement, onDecrementToMin, onIncrement, onIncrementToMax, parseValue, readOnly, step, value, } = useInputNumberContext(NUMBER_INPUT_FIELD_NAME, __scopeInputNumber);
|
|
119
|
+
/**
|
|
120
|
+
* Handles the blur event to format the value of the input.
|
|
121
|
+
*
|
|
122
|
+
* @param event - The blur event triggered when the input loses focus.
|
|
123
|
+
*/
|
|
124
|
+
const handleBlur = useCallback((event) => {
|
|
125
|
+
const numericValue = parseValue(event.target.value);
|
|
126
|
+
const formattedValue = formatValue(numericValue);
|
|
127
|
+
if (formattedValue !== event.target.value) {
|
|
128
|
+
event.target.value = formattedValue;
|
|
129
|
+
}
|
|
130
|
+
onChange(numericValue);
|
|
131
|
+
}, [formatValue, onChange, parseValue]);
|
|
132
|
+
/**
|
|
133
|
+
* Handles keydown events to increment, decrement, or perform other actions.
|
|
134
|
+
*
|
|
135
|
+
* @param event - The keyboard event triggered by key presses.
|
|
136
|
+
*/
|
|
137
|
+
const handleKeyDown = useCallback((event) => {
|
|
138
|
+
switch (event.key) {
|
|
139
|
+
case "ArrowUp": {
|
|
140
|
+
onIncrement();
|
|
141
|
+
event.preventDefault();
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
case "PageUp": {
|
|
145
|
+
onIncrementToMax();
|
|
146
|
+
event.preventDefault();
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case "ArrowDown": {
|
|
150
|
+
onDecrement();
|
|
151
|
+
event.preventDefault();
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
case "PageDown": {
|
|
155
|
+
onDecrementToMin();
|
|
156
|
+
event.preventDefault();
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
default: {
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}, [onIncrement, onIncrementToMax, onDecrement, onDecrementToMin]);
|
|
164
|
+
/**
|
|
165
|
+
* Prevents invalid keyboard input for the numeric input field.
|
|
166
|
+
*
|
|
167
|
+
* @param event - The keyboard event to handle.
|
|
168
|
+
*/
|
|
169
|
+
const handleKeyDownPrevent = useCallback((event) => {
|
|
170
|
+
switch (event.key) {
|
|
171
|
+
case "ArrowUp":
|
|
172
|
+
case "ArrowDown":
|
|
173
|
+
case "ArrowLeft":
|
|
174
|
+
case "ArrowRight":
|
|
175
|
+
case "PageUp":
|
|
176
|
+
case "PageDown":
|
|
177
|
+
case "Tab":
|
|
178
|
+
case "Escape":
|
|
179
|
+
case "Enter":
|
|
180
|
+
case "Backspace":
|
|
181
|
+
case "Delete":
|
|
182
|
+
case "Home":
|
|
183
|
+
case "End":
|
|
184
|
+
case ".":
|
|
185
|
+
case ",":
|
|
186
|
+
case "-":
|
|
187
|
+
case "%": {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
default: {
|
|
191
|
+
if (isNumberKey(event.key) || isModifierKey(event) || isFunctionKey(event.key)) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
event.preventDefault();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}, []);
|
|
198
|
+
/**
|
|
199
|
+
* Handles the Enter key to format the value of the input.
|
|
200
|
+
*
|
|
201
|
+
* @param event - The keyboard event triggered by pressing Enter.
|
|
202
|
+
*/
|
|
203
|
+
const handleKeyDownEnter = useCallback((event) => {
|
|
204
|
+
const inputElement = inputRef.current;
|
|
205
|
+
if (event.key !== "Enter" || !inputElement) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const numericValue = parseValue(inputElement.value);
|
|
209
|
+
const formattedValue = formatValue(numericValue);
|
|
210
|
+
if (formattedValue !== inputElement.value) {
|
|
211
|
+
inputElement.value = formattedValue;
|
|
212
|
+
}
|
|
213
|
+
onChange(numericValue);
|
|
214
|
+
}, [formatValue, inputRef, onChange, parseValue]);
|
|
215
|
+
/**
|
|
216
|
+
* Creates a combined keydown event handler that processes keyboard events in sequence.
|
|
217
|
+
*
|
|
218
|
+
* The handler chain executes in the following order:
|
|
219
|
+
* 1. User-provided onKeyDown handler (if any)
|
|
220
|
+
* 2. handleKeyDownPrevent - Prevents non-numeric input
|
|
221
|
+
* 3. handleKeyDown - Handles arrow keys and page up/down for value adjustments
|
|
222
|
+
* 4. handleKeyDownEnter - Handles Enter key press to format and update the value
|
|
223
|
+
*
|
|
224
|
+
* @returns A composed event handler function for the onKeyDown event
|
|
225
|
+
*/
|
|
226
|
+
const combinedKeyDownHandler = useCallback((event) => {
|
|
227
|
+
composeEventHandlers(onKeyDown, chain(handleKeyDownPrevent, handleKeyDown, handleKeyDownEnter))(event);
|
|
228
|
+
}, [onKeyDown, handleKeyDown, handleKeyDownEnter, handleKeyDownPrevent]);
|
|
229
|
+
/**
|
|
230
|
+
* Adds a listener to handle wheel events for incrementing or decrementing the value.
|
|
231
|
+
*/
|
|
232
|
+
useEffect(() => {
|
|
233
|
+
const handleWheel = (event) => {
|
|
234
|
+
const inputElement = inputRef.current;
|
|
235
|
+
if (!inputElement || disabled || readOnly || document.activeElement !== inputElement) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
event.preventDefault();
|
|
239
|
+
if (event.deltaY > 0) {
|
|
240
|
+
onIncrement();
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
onDecrement();
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
const inputElement = inputRef.current;
|
|
247
|
+
inputElement?.addEventListener("wheel", handleWheel);
|
|
248
|
+
return () => {
|
|
249
|
+
inputElement?.removeEventListener("wheel", handleWheel);
|
|
250
|
+
};
|
|
251
|
+
}, [onIncrement, onDecrement, inputRef, disabled, readOnly]);
|
|
252
|
+
/**
|
|
253
|
+
* Updates the input field's value when it changes in the context.
|
|
254
|
+
*/
|
|
255
|
+
useEffect(() => {
|
|
256
|
+
const inputElement = inputRef.current;
|
|
257
|
+
if (inputElement && inputElement !== document.activeElement) {
|
|
258
|
+
inputElement.value = formatValue(value);
|
|
259
|
+
}
|
|
260
|
+
}, [formatValue, inputRef, value]);
|
|
261
|
+
/**
|
|
262
|
+
* Adds a listener to handle form reset events by clearing the input value.
|
|
263
|
+
*/
|
|
264
|
+
useEffect(() => {
|
|
265
|
+
const inputElement = inputRef.current;
|
|
266
|
+
if (!inputElement) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const handleReset = () => {
|
|
270
|
+
onChange(parseValue(defaultValue));
|
|
271
|
+
};
|
|
272
|
+
const form = inputElement.form;
|
|
273
|
+
form?.addEventListener("reset", handleReset);
|
|
274
|
+
return () => {
|
|
275
|
+
form?.removeEventListener("reset", handleReset);
|
|
276
|
+
};
|
|
277
|
+
}, [defaultValue, inputRef, onChange, parseValue]);
|
|
278
|
+
return (_jsx(InputPrimitive.Field, { ref: inputRef, defaultValue: formatValue(value), disabled: disabled, id: id, inputMode: "decimal", max: max, min: min, readOnly: readOnly, step: step, onBlur: composeEventHandlers(onBlur, handleBlur), onKeyDown: combinedKeyDownHandler, ...inputScope, ...props }));
|
|
327
279
|
}
|
|
280
|
+
/* -----------------------------------------------------------------------------
|
|
281
|
+
* Component: NumberStepperButton
|
|
282
|
+
* -------------------------------------------------------------------------- */
|
|
328
283
|
/**
|
|
329
|
-
* The name of the NumberStepperButton component constant.
|
|
330
|
-
*/
|
|
284
|
+
* The name of the NumberStepperButton component constant.
|
|
285
|
+
*/
|
|
331
286
|
const NUMBER_STEPPER_BUTTON_NAME = "NumberStepperButton";
|
|
332
287
|
function NumberStepperButton({ __scopeInputNumber, operation, ...props }) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
}, [
|
|
402
|
-
onDecrement,
|
|
403
|
-
onIncrement,
|
|
404
|
-
operation
|
|
405
|
-
]);
|
|
406
|
-
return /* @__PURE__ */ jsx("button", {
|
|
407
|
-
"aria-controls": id,
|
|
408
|
-
"aria-label": operation === "increment" ? ariaIncrementLabel : ariaDecrementLabel,
|
|
409
|
-
"aria-live": "polite",
|
|
410
|
-
disabled: isDisabled,
|
|
411
|
-
type: "button",
|
|
412
|
-
onContextMenu: handleContextMenu,
|
|
413
|
-
onKeyDown: handleKeyDown,
|
|
414
|
-
onPointerCancel: clearActionInterval,
|
|
415
|
-
onPointerDown: handlePointerDown,
|
|
416
|
-
onPointerLeave: clearActionInterval,
|
|
417
|
-
onPointerUp: clearActionInterval,
|
|
418
|
-
...props
|
|
419
|
-
});
|
|
288
|
+
// Destructures relevant context values for the button functionality.
|
|
289
|
+
const { ariaDecrementLabel, ariaIncrementLabel, disabled, id, max, min, onDecrement, onIncrement, value, } = useInputNumberContext(NUMBER_STEPPER_BUTTON_NAME, __scopeInputNumber);
|
|
290
|
+
const isDisabled = useMemo(() => {
|
|
291
|
+
const atMin = min !== undefined && value !== undefined && value <= min;
|
|
292
|
+
const atMax = max !== undefined && value !== undefined && value >= max;
|
|
293
|
+
return (disabled ?? atMin) || atMax;
|
|
294
|
+
}, [min, max, value, disabled]);
|
|
295
|
+
/**
|
|
296
|
+
* Ref to store a timeout ID for managing repeated button actions.
|
|
297
|
+
*/
|
|
298
|
+
const timeoutIdRef = useRef(null);
|
|
299
|
+
/**
|
|
300
|
+
* Starts a repeated action at a regular interval.
|
|
301
|
+
* The action begins immediately and then continues with a delay.
|
|
302
|
+
*
|
|
303
|
+
* @param callback - The callback function to execute repeatedly.
|
|
304
|
+
*/
|
|
305
|
+
const startActionInterval = useCallback((callback) => {
|
|
306
|
+
// Time between repeated actions (in milliseconds).
|
|
307
|
+
const interval = 100;
|
|
308
|
+
// Function to perform the action and set the next interval.
|
|
309
|
+
const repeatAction = () => {
|
|
310
|
+
callback();
|
|
311
|
+
timeoutIdRef.current = setTimeout(repeatAction, interval);
|
|
312
|
+
};
|
|
313
|
+
callback();
|
|
314
|
+
timeoutIdRef.current = setTimeout(repeatAction, interval * 2);
|
|
315
|
+
}, []);
|
|
316
|
+
/**
|
|
317
|
+
* Clears any ongoing action intervals.
|
|
318
|
+
*/
|
|
319
|
+
const clearActionInterval = useCallback(() => {
|
|
320
|
+
if (timeoutIdRef.current) {
|
|
321
|
+
clearTimeout(timeoutIdRef.current);
|
|
322
|
+
timeoutIdRef.current = null;
|
|
323
|
+
}
|
|
324
|
+
}, []);
|
|
325
|
+
/**
|
|
326
|
+
* Handles pointer down events and triggers the appropriate action
|
|
327
|
+
* (`increment` or `decrement`).
|
|
328
|
+
*/
|
|
329
|
+
const handlePointerDown = useCallback(() => {
|
|
330
|
+
const action = operation === "increment" ? onIncrement : onDecrement;
|
|
331
|
+
startActionInterval(action);
|
|
332
|
+
}, [onDecrement, onIncrement, operation, startActionInterval]);
|
|
333
|
+
/**
|
|
334
|
+
* Prevents the context menu from displaying when the button is right-clicked.
|
|
335
|
+
*
|
|
336
|
+
* @param event - The mouse event triggered by the right-click.
|
|
337
|
+
*/
|
|
338
|
+
const handleContextMenu = useCallback((event) => {
|
|
339
|
+
event.preventDefault();
|
|
340
|
+
}, []);
|
|
341
|
+
/**
|
|
342
|
+
* Handles keyboard events to support activation of the button using
|
|
343
|
+
* keyboard navigation (Enter or Space).
|
|
344
|
+
*
|
|
345
|
+
* @param event - The keyboard event with the triggered key.
|
|
346
|
+
*/
|
|
347
|
+
const handleKeyDown = useCallback((event) => {
|
|
348
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
349
|
+
event.preventDefault();
|
|
350
|
+
const action = operation === "increment" ? onIncrement : onDecrement;
|
|
351
|
+
action();
|
|
352
|
+
}
|
|
353
|
+
}, [onDecrement, onIncrement, operation]);
|
|
354
|
+
return (_jsx("button", { "aria-controls": id, "aria-label": operation === "increment" ? ariaIncrementLabel : ariaDecrementLabel, "aria-live": "polite", disabled: isDisabled, type: "button", onContextMenu: handleContextMenu, onKeyDown: handleKeyDown, onPointerCancel: clearActionInterval, onPointerDown: handlePointerDown, onPointerLeave: clearActionInterval, onPointerUp: clearActionInterval, ...props }));
|
|
420
355
|
}
|
|
421
356
|
function InputNumberIncrementButton(props) {
|
|
422
|
-
|
|
423
|
-
operation: "increment",
|
|
424
|
-
...props
|
|
425
|
-
});
|
|
357
|
+
return _jsx(NumberStepperButton, { operation: "increment", ...props });
|
|
426
358
|
}
|
|
427
359
|
function InputNumberDecrementButton(props) {
|
|
428
|
-
|
|
429
|
-
operation: "decrement",
|
|
430
|
-
...props
|
|
431
|
-
});
|
|
360
|
+
return _jsx(NumberStepperButton, { operation: "decrement", ...props });
|
|
432
361
|
}
|
|
362
|
+
/* -----------------------------------------------------------------------------
|
|
363
|
+
* Utility Functions
|
|
364
|
+
* -------------------------------------------------------------------------- */
|
|
433
365
|
/**
|
|
434
|
-
* Chains multiple callbacks into a single function
|
|
435
|
-
*
|
|
436
|
-
* @param callbacks - Array of callback functions that will be executed in order
|
|
437
|
-
* @returns A single function that executes all callbacks
|
|
438
|
-
*/
|
|
366
|
+
* Chains multiple callbacks into a single function
|
|
367
|
+
*
|
|
368
|
+
* @param callbacks - Array of callback functions that will be executed in order
|
|
369
|
+
* @returns A single function that executes all callbacks
|
|
370
|
+
*/
|
|
439
371
|
function chain(...callbacks) {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
372
|
+
return (...args) => {
|
|
373
|
+
for (const callback of callbacks) {
|
|
374
|
+
callback(...args);
|
|
375
|
+
}
|
|
376
|
+
};
|
|
443
377
|
}
|
|
444
378
|
/**
|
|
445
|
-
* Extracts decimal and a thousand separators from a given locale's number format
|
|
446
|
-
*
|
|
447
|
-
* @param locale - The locale string to use for number formatting (e.g., 'en-US', 'de-DE')
|
|
448
|
-
* @returns Object containing decimal and a thousand separators
|
|
449
|
-
*/
|
|
379
|
+
* Extracts decimal and a thousand separators from a given locale's number format
|
|
380
|
+
*
|
|
381
|
+
* @param locale - The locale string to use for number formatting (e.g., 'en-US', 'de-DE')
|
|
382
|
+
* @returns Object containing decimal and a thousand separators
|
|
383
|
+
*/
|
|
450
384
|
function getNumberFormatSeparators(locale) {
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
385
|
+
const numberFormat = new Intl.NumberFormat(locale);
|
|
386
|
+
const parts = numberFormat.formatToParts(12_345.6);
|
|
387
|
+
let thousandSeparator = "";
|
|
388
|
+
let decimalSeparator = "";
|
|
389
|
+
for (const part of parts) {
|
|
390
|
+
if (part.type === "group") {
|
|
391
|
+
thousandSeparator = part.value;
|
|
392
|
+
}
|
|
393
|
+
if (part.type === "decimal") {
|
|
394
|
+
decimalSeparator = part.value;
|
|
395
|
+
}
|
|
396
|
+
// Stop early if you've found enough.
|
|
397
|
+
if (thousandSeparator && decimalSeparator) {
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return { decimalSeparator, thousandSeparator };
|
|
463
402
|
}
|
|
464
403
|
/**
|
|
465
|
-
* Normalizes an input value by removing formatting characters
|
|
466
|
-
*
|
|
467
|
-
* @param value - The input string to normalize
|
|
468
|
-
* @param thousandSeparator - The thousand-separator character to remove
|
|
469
|
-
* @param decimalSeparator - The decimal separator to convert to standard dot notation
|
|
470
|
-
* @returns Normalized string value ready for numeric conversion
|
|
471
|
-
*/
|
|
404
|
+
* Normalizes an input value by removing formatting characters
|
|
405
|
+
*
|
|
406
|
+
* @param value - The input string to normalize
|
|
407
|
+
* @param thousandSeparator - The thousand-separator character to remove
|
|
408
|
+
* @param decimalSeparator - The decimal separator to convert to standard dot notation
|
|
409
|
+
* @returns Normalized string value ready for numeric conversion
|
|
410
|
+
*/
|
|
472
411
|
function normalizeInputValue(value, thousandSeparator, decimalSeparator) {
|
|
473
|
-
|
|
412
|
+
return value
|
|
413
|
+
.replaceAll(new RegExp(`\\${thousandSeparator}`, "g"), "")
|
|
414
|
+
.replace(new RegExp(`\\${decimalSeparator}`), ".")
|
|
415
|
+
.replaceAll(/[()]/g, "-");
|
|
474
416
|
}
|
|
475
417
|
/**
|
|
476
|
-
* Checks if a keyboard event includes modifier keys (Ctrl, Alt, Meta, Shift)
|
|
477
|
-
*
|
|
478
|
-
* @param event - The keyboard event to check
|
|
479
|
-
* @returns True if any modifier key is pressed
|
|
480
|
-
*/
|
|
418
|
+
* Checks if a keyboard event includes modifier keys (Ctrl, Alt, Meta, Shift)
|
|
419
|
+
*
|
|
420
|
+
* @param event - The keyboard event to check
|
|
421
|
+
* @returns True if any modifier key is pressed
|
|
422
|
+
*/
|
|
481
423
|
function isModifierKey(event) {
|
|
482
|
-
|
|
424
|
+
return event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
|
|
483
425
|
}
|
|
484
426
|
/**
|
|
485
|
-
* Determines if a key is a function key (F1-F12)
|
|
486
|
-
*
|
|
487
|
-
* @param key - The key name to check
|
|
488
|
-
* @returns True if the key is a function key
|
|
489
|
-
*/
|
|
427
|
+
* Determines if a key is a function key (F1-F12)
|
|
428
|
+
*
|
|
429
|
+
* @param key - The key name to check
|
|
430
|
+
* @returns True if the key is a function key
|
|
431
|
+
*/
|
|
490
432
|
function isFunctionKey(key) {
|
|
491
|
-
|
|
433
|
+
return key.startsWith("F") && key.length > 1;
|
|
492
434
|
}
|
|
493
435
|
/**
|
|
494
|
-
* Checks if a key represents a number (0-9)
|
|
495
|
-
*
|
|
496
|
-
* @param key - The key name to check
|
|
497
|
-
* @returns True if the key represents a number
|
|
498
|
-
*/
|
|
436
|
+
* Checks if a key represents a number (0-9)
|
|
437
|
+
*
|
|
438
|
+
* @param key - The key name to check
|
|
439
|
+
* @returns True if the key represents a number
|
|
440
|
+
*/
|
|
499
441
|
function isNumberKey(key) {
|
|
500
|
-
|
|
442
|
+
return !Number.isNaN(Number(key));
|
|
501
443
|
}
|
|
502
444
|
/**
|
|
503
|
-
* Clamps a numeric value between a minimum and maximum
|
|
504
|
-
*
|
|
505
|
-
* @param value - The value to clamp
|
|
506
|
-
* @param min - The minimum allowed value (defaults to \-Infinity)
|
|
507
|
-
* @param max - The maximum allowed value (defaults to Infinity)
|
|
508
|
-
* @returns The clamped value
|
|
509
|
-
*/
|
|
445
|
+
* Clamps a numeric value between a minimum and maximum
|
|
446
|
+
*
|
|
447
|
+
* @param value - The value to clamp
|
|
448
|
+
* @param min - The minimum allowed value (defaults to \-Infinity)
|
|
449
|
+
* @param max - The maximum allowed value (defaults to Infinity)
|
|
450
|
+
* @returns The clamped value
|
|
451
|
+
*/
|
|
510
452
|
function clamp(value, min = Number.NEGATIVE_INFINITY, max = Number.POSITIVE_INFINITY) {
|
|
511
|
-
|
|
453
|
+
return Math.min(Math.max(value, min), max);
|
|
512
454
|
}
|
|
513
|
-
|
|
514
|
-
|
|
455
|
+
/* -----------------------------------------------------------------------------
|
|
456
|
+
* Exports
|
|
457
|
+
* -------------------------------------------------------------------------- */
|
|
458
|
+
export { createInputNumberScope, InputNumberDecrementButton as DecrementButton, InputNumberField as Field, InputNumberIncrementButton as IncrementButton, InputNumber, InputNumberDecrementButton, InputNumberField, InputNumberIncrementButton, InputNumber as Root, };
|