raqam 0.2.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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +344 -0
  3. package/dist/chunk-IG7CVIA2.js +14 -0
  4. package/dist/chunk-IG7CVIA2.js.map +1 -0
  5. package/dist/chunk-NBAZIJ5W.js +25 -0
  6. package/dist/chunk-NBAZIJ5W.js.map +1 -0
  7. package/dist/chunk-NSFX2EAT.js +14 -0
  8. package/dist/chunk-NSFX2EAT.js.map +1 -0
  9. package/dist/chunk-NTROGAES.js +14 -0
  10. package/dist/chunk-NTROGAES.js.map +1 -0
  11. package/dist/chunk-VOBTYII2.js +14 -0
  12. package/dist/chunk-VOBTYII2.js.map +1 -0
  13. package/dist/chunk-WTS5RY7S.js +16 -0
  14. package/dist/chunk-WTS5RY7S.js.map +1 -0
  15. package/dist/core.cjs +2 -0
  16. package/dist/core.cjs.map +1 -0
  17. package/dist/core.d.cts +351 -0
  18. package/dist/core.d.ts +351 -0
  19. package/dist/core.js +2 -0
  20. package/dist/core.js.map +1 -0
  21. package/dist/index-B8X3-9h1.d.cts +343 -0
  22. package/dist/index-B8X3-9h1.d.ts +343 -0
  23. package/dist/index.cjs +3 -0
  24. package/dist/index.cjs.map +1 -0
  25. package/dist/index.d.cts +193 -0
  26. package/dist/index.d.ts +193 -0
  27. package/dist/index.js +3 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/locales/ar.cjs +36 -0
  30. package/dist/locales/ar.cjs.map +1 -0
  31. package/dist/locales/ar.d.cts +4 -0
  32. package/dist/locales/ar.d.ts +4 -0
  33. package/dist/locales/ar.js +4 -0
  34. package/dist/locales/ar.js.map +1 -0
  35. package/dist/locales/bn.cjs +36 -0
  36. package/dist/locales/bn.cjs.map +1 -0
  37. package/dist/locales/bn.d.cts +4 -0
  38. package/dist/locales/bn.d.ts +4 -0
  39. package/dist/locales/bn.js +4 -0
  40. package/dist/locales/bn.js.map +1 -0
  41. package/dist/locales/fa.cjs +38 -0
  42. package/dist/locales/fa.cjs.map +1 -0
  43. package/dist/locales/fa.d.cts +4 -0
  44. package/dist/locales/fa.d.ts +4 -0
  45. package/dist/locales/fa.js +4 -0
  46. package/dist/locales/fa.js.map +1 -0
  47. package/dist/locales/hi.cjs +36 -0
  48. package/dist/locales/hi.cjs.map +1 -0
  49. package/dist/locales/hi.d.cts +4 -0
  50. package/dist/locales/hi.d.ts +4 -0
  51. package/dist/locales/hi.js +4 -0
  52. package/dist/locales/hi.js.map +1 -0
  53. package/dist/locales/index.cjs +78 -0
  54. package/dist/locales/index.cjs.map +1 -0
  55. package/dist/locales/index.d.cts +5 -0
  56. package/dist/locales/index.d.ts +5 -0
  57. package/dist/locales/index.js +8 -0
  58. package/dist/locales/index.js.map +1 -0
  59. package/dist/locales/th.cjs +36 -0
  60. package/dist/locales/th.cjs.map +1 -0
  61. package/dist/locales/th.d.cts +4 -0
  62. package/dist/locales/th.d.ts +4 -0
  63. package/dist/locales/th.js +4 -0
  64. package/dist/locales/th.js.map +1 -0
  65. package/dist/react.cjs +3 -0
  66. package/dist/react.cjs.map +1 -0
  67. package/dist/react.d.cts +3 -0
  68. package/dist/react.d.ts +3 -0
  69. package/dist/react.js +3 -0
  70. package/dist/react.js.map +1 -0
  71. package/package.json +170 -0
@@ -0,0 +1,343 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React$1 from 'react';
3
+ import React__default, { RefObject } from 'react';
4
+
5
+ interface LocaleInfo {
6
+ /** Decimal separator for this locale (e.g. "." en-US, "," de-DE, "٫" fa-IR) */
7
+ decimalSeparator: string;
8
+ /** Grouping (thousands) separator (e.g. "," en-US, "." de-DE, "٬" fa-IR) */
9
+ groupingSeparator: string;
10
+ /** Minus sign character (usually "-" but can differ) */
11
+ minusSign: string;
12
+ /** Locale's representation of "0" (e.g. "0" for Latin, "۰" for Persian) */
13
+ zero: string;
14
+ /** Whether this is an RTL locale */
15
+ isRTL: boolean;
16
+ }
17
+ interface FormatResult {
18
+ formatted: string;
19
+ parts: Intl.NumberFormatPart[];
20
+ }
21
+ interface ParseResult {
22
+ /** The parsed number, or null if empty / un-parseable */
23
+ value: number | null;
24
+ /** True for valid numbers */
25
+ isValid: boolean;
26
+ /**
27
+ * True for valid-but-incomplete input that must not be reformatted yet:
28
+ * "-", "1.", "1.0", "1.00", etc.
29
+ */
30
+ isIntermediate: boolean;
31
+ }
32
+ /**
33
+ * boolean[] of length formattedValue.length + 1.
34
+ * true → cursor may rest at this index
35
+ * false → cursor must not rest here (e.g. inside a thousands separator)
36
+ */
37
+ type CaretBoundary = boolean[];
38
+ /** Unicode codepoint range [start, end] inclusive representing a digit block */
39
+ type DigitBlock = readonly [number, number];
40
+ interface UseNumberFieldStateOptions {
41
+ /** Controlled numeric value */
42
+ value?: number | null;
43
+ /** Uncontrolled default value */
44
+ defaultValue?: number | null;
45
+ /** Fires on every meaningful value change */
46
+ onChange?: (value: number | null) => void;
47
+ /** BCP 47 locale tag (default: browser locale) */
48
+ locale?: string;
49
+ /** Full Intl.NumberFormatOptions — currency, percent, decimal, etc. */
50
+ formatOptions?: Intl.NumberFormatOptions;
51
+ /** Minimum allowed value */
52
+ minValue?: number;
53
+ /** Maximum allowed value */
54
+ maxValue?: number;
55
+ /** Step amount for increment/decrement (default: 1) */
56
+ step?: number;
57
+ /** Large step — Shift+Arrow / PageUp/Down (default: step * 10) */
58
+ largeStep?: number;
59
+ /** Small step — Meta/Ctrl+Arrow (default: step * 0.1) */
60
+ smallStep?: number;
61
+ /** Allow negative values (default: true) */
62
+ allowNegative?: boolean;
63
+ /** Allow decimal values (default: true) */
64
+ allowDecimal?: boolean;
65
+ /** Override maximumFractionDigits from formatOptions */
66
+ maximumFractionDigits?: number;
67
+ /** Override minimumFractionDigits from formatOptions */
68
+ minimumFractionDigits?: number;
69
+ /** Always show exactly maximumFractionDigits decimal places */
70
+ fixedDecimalScale?: boolean;
71
+ /** When clamping happens (default: "blur") */
72
+ clampBehavior?: "blur" | "strict" | "none";
73
+ /** Apply live formatting while typing (default: true) */
74
+ liveFormat?: boolean;
75
+ /** Arbitrary prefix string (e.g. "$") */
76
+ prefix?: string;
77
+ /** Arbitrary suffix string (e.g. " تومان") */
78
+ suffix?: string;
79
+ /** Disable the field */
80
+ disabled?: boolean;
81
+ /** Make the field read-only */
82
+ readOnly?: boolean;
83
+ /** Mark the field as required */
84
+ required?: boolean;
85
+ /**
86
+ * Allow values outside min/max to be typed and committed without clamping.
87
+ * Useful when server-side validation handles clamping.
88
+ * When true, aria-invalid is set when value is out of range.
89
+ * default: false
90
+ */
91
+ allowOutOfRange?: boolean;
92
+ /**
93
+ * Custom validation function. Called on every value change.
94
+ * - Return `true` or `null`/`undefined` → valid
95
+ * - Return `false` → invalid (aria-invalid set, no error message)
96
+ * - Return a `string` → invalid with that string as the error message
97
+ */
98
+ validate?: (value: number | null) => boolean | string | null | undefined;
99
+ /**
100
+ * Fires with the raw unformatted string the user typed, preserving full
101
+ * decimal precision before JS float conversion. Useful for financial apps
102
+ * that need arbitrary-precision string arithmetic.
103
+ * Fires alongside `onChange`.
104
+ */
105
+ onRawChange?: (rawValue: string | null) => void;
106
+ /**
107
+ * Custom format function. When provided, replaces the built-in Intl.NumberFormat
108
+ * formatter for display purposes. Also used for initial display value.
109
+ */
110
+ formatValue?: (value: number) => string;
111
+ /**
112
+ * Custom parse function. When provided, replaces the built-in locale-aware parser.
113
+ * Must return `{ value: number | null, isIntermediate: boolean }`.
114
+ */
115
+ parseValue?: (input: string) => {
116
+ value: number | null;
117
+ isIntermediate: boolean;
118
+ };
119
+ }
120
+ interface NumberFieldState {
121
+ /** The display string shown in the input */
122
+ inputValue: string;
123
+ /** The parsed numeric value (null for empty/invalid) */
124
+ numberValue: number | null;
125
+ /**
126
+ * The raw string value exactly as the user typed it (before formatting).
127
+ * Preserves full decimal precision — useful for financial arbitrary-precision math.
128
+ */
129
+ rawValue: string | null;
130
+ /** Whether increment is currently possible */
131
+ canIncrement: boolean;
132
+ /** Whether decrement is currently possible */
133
+ canDecrement: boolean;
134
+ /** Whether the ScrubArea is currently being dragged */
135
+ isScrubbing: boolean;
136
+ /** Update the isScrubbing state (called by useScrubArea) */
137
+ setIsScrubbing: (val: boolean) => void;
138
+ /** Whether the input is currently focused */
139
+ isFocused: boolean;
140
+ /** Update the isFocused state (called by useNumberField) */
141
+ setIsFocused: (val: boolean) => void;
142
+ /** Current validation state — 'valid' if no validate prop, or based on validate result */
143
+ validationState: "valid" | "invalid";
144
+ /** Error message from validate() if it returned a string, otherwise null */
145
+ validationError: string | null;
146
+ /** Internal: set the reason for the next onChange call (used by useNumberField) */
147
+ _setLastChangeReason: (reason: ChangeReason) => void;
148
+ /** Internal: read the current change reason (used by NumberField.Root) */
149
+ _getLastChangeReason: () => ChangeReason;
150
+ /** Update display string (triggers parse + onChange) */
151
+ setInputValue: (val: string) => void;
152
+ /** Directly set the numeric value (triggers format + onChange) */
153
+ setNumberValue: (val: number | null) => void;
154
+ /** Format + clamp on blur — call from onBlur */
155
+ commit: () => void;
156
+ /** Increment by step */
157
+ increment: (amount?: number) => void;
158
+ /** Decrement by step */
159
+ decrement: (amount?: number) => void;
160
+ /** Jump to maxValue */
161
+ incrementToMax: () => void;
162
+ /** Jump to minValue */
163
+ decrementToMin: () => void;
164
+ /** Raw options (for hooks that need them) */
165
+ options: UseNumberFieldStateOptions;
166
+ }
167
+ /** Reason for a value change — propagated through onValueChange details */
168
+ type ChangeReason = "input" | "clear" | "blur" | "paste" | "keyboard" | "increment" | "decrement" | "wheel" | "scrub";
169
+ interface UseNumberFieldProps extends UseNumberFieldStateOptions {
170
+ /** Visible label text (used for aria-label fallback) */
171
+ label?: string;
172
+ "aria-label"?: string;
173
+ "aria-describedby"?: string;
174
+ "aria-labelledby"?: string;
175
+ /** Form field name — renders a hidden input */
176
+ name?: string;
177
+ /** id for the input element */
178
+ id?: string;
179
+ /** Enable mouse-wheel increment/decrement */
180
+ allowMouseWheel?: boolean;
181
+ /**
182
+ * Controls what is placed in the clipboard on copy/cut.
183
+ * - 'formatted' (default): browser-native copy of display string
184
+ * - 'raw': numberValue as a plain JS number string (e.g. "1234.56")
185
+ * - 'number': alias for 'raw'
186
+ */
187
+ copyBehavior?: "formatted" | "raw" | "number";
188
+ /** Milliseconds before press-and-hold repeat starts (default: 400) */
189
+ stepHoldDelay?: number;
190
+ /** Initial milliseconds between repeats during press-and-hold (default: 200) */
191
+ stepHoldInterval?: number;
192
+ onFocus?: (e: React.FocusEvent<HTMLInputElement>) => void;
193
+ onBlur?: (e: React.FocusEvent<HTMLInputElement>) => void;
194
+ }
195
+ interface NumberFieldAria {
196
+ labelProps: React.LabelHTMLAttributes<HTMLLabelElement>;
197
+ groupProps: React.HTMLAttributes<HTMLDivElement>;
198
+ inputProps: React.InputHTMLAttributes<HTMLInputElement>;
199
+ hiddenInputProps: React.InputHTMLAttributes<HTMLInputElement> | null;
200
+ incrementButtonProps: React.ButtonHTMLAttributes<HTMLButtonElement>;
201
+ decrementButtonProps: React.ButtonHTMLAttributes<HTMLButtonElement>;
202
+ descriptionProps: React.HTMLAttributes<HTMLElement>;
203
+ errorMessageProps: React.HTMLAttributes<HTMLElement>;
204
+ }
205
+ interface ScrubAreaOptions {
206
+ /**
207
+ * Axis to scrub on.
208
+ * - 'horizontal' (default): dragging right increments, left decrements
209
+ * - 'vertical': dragging up increments, down decrements
210
+ * - 'both': uses whichever axis has greater movement
211
+ */
212
+ direction?: "horizontal" | "vertical" | "both";
213
+ /** Pixels of drag movement required for one step (default: 4) */
214
+ pixelSensitivity?: number;
215
+ }
216
+ type StateRenderFn = (props: Record<string, unknown>, state: NumberFieldState) => React.ReactElement;
217
+ type RenderProp = React.ReactElement | StateRenderFn;
218
+ interface ScrubAreaProps extends ScrubAreaOptions, Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
219
+ render?: RenderProp;
220
+ children?: React.ReactNode;
221
+ }
222
+ interface ScrubAreaCursorProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
223
+ render?: RenderProp;
224
+ children?: React.ReactNode;
225
+ }
226
+ interface NumberFieldRootProps extends UseNumberFieldProps {
227
+ children?: React.ReactNode;
228
+ /** CSS class for the root wrapper div */
229
+ className?: string;
230
+ /** Inline style for the root wrapper div */
231
+ style?: React.CSSProperties;
232
+ /** Fires on every meaningful value change */
233
+ onValueChange?: (value: number | null, details: {
234
+ reason: ChangeReason;
235
+ formattedValue: string;
236
+ event?: React.SyntheticEvent;
237
+ }) => void;
238
+ /** Fires only on commit (blur, Enter) */
239
+ onValueCommitted?: (value: number | null, details: {
240
+ reason: "blur" | "keyboard";
241
+ }) => void;
242
+ }
243
+
244
+ declare function useNumberFieldState(options: UseNumberFieldStateOptions): NumberFieldState;
245
+
246
+ declare function useNumberField(props: UseNumberFieldProps, state: NumberFieldState, inputRef: React.RefObject<HTMLInputElement | null>): NumberFieldAria;
247
+
248
+ type FormatOptions = Pick<UseNumberFieldStateOptions, "locale" | "formatOptions" | "prefix" | "suffix" | "minimumFractionDigits" | "maximumFractionDigits" | "fixedDecimalScale">;
249
+ /**
250
+ * Lightweight display-only formatting hook. Returns the formatted string for
251
+ * a numeric value using the same Intl.NumberFormat engine as the full input.
252
+ *
253
+ * Use this when you need to display a formatted number in a read-only context
254
+ * (table cells, summaries, labels) without the overhead of a full input state machine.
255
+ *
256
+ * @example
257
+ * const price = useNumberFieldFormat(1234567.89, {
258
+ * locale: 'en-US',
259
+ * formatOptions: { style: 'currency', currency: 'USD' },
260
+ * })
261
+ * // price === "$1,234,567.89"
262
+ *
263
+ * @example
264
+ * const pct = useNumberFieldFormat(0.4267, {
265
+ * formatOptions: { style: 'percent', maximumFractionDigits: 1 },
266
+ * })
267
+ * // pct === "42.7%"
268
+ */
269
+ declare function useNumberFieldFormat(value: number | null, options?: FormatOptions): string;
270
+
271
+ interface UseControllableStateOptions<T> {
272
+ value?: T;
273
+ defaultValue?: T;
274
+ onChange?: (value: T) => void;
275
+ }
276
+ /**
277
+ * Manages controlled vs uncontrolled state.
278
+ * - If `value` is provided, the component is controlled.
279
+ * - Otherwise it manages its own state starting from `defaultValue`.
280
+ * Warns in dev mode if the component switches between controlled/uncontrolled.
281
+ */
282
+ declare function useControllableState<T>({ value, defaultValue, onChange, }: UseControllableStateOptions<T>): [
283
+ T | undefined,
284
+ (next: T | ((prev: T | undefined) => T)) => void
285
+ ];
286
+
287
+ interface LabelProps extends React__default.LabelHTMLAttributes<HTMLLabelElement> {
288
+ render?: RenderProp;
289
+ children?: React__default.ReactNode;
290
+ }
291
+ interface GroupProps extends React__default.HTMLAttributes<HTMLDivElement> {
292
+ render?: RenderProp;
293
+ children?: React__default.ReactNode;
294
+ }
295
+ interface InputProps extends Omit<React__default.InputHTMLAttributes<HTMLInputElement>, "type"> {
296
+ render?: RenderProp;
297
+ }
298
+ interface IncrementProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
299
+ render?: RenderProp;
300
+ children?: React__default.ReactNode;
301
+ }
302
+ interface DecrementProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
303
+ render?: RenderProp;
304
+ children?: React__default.ReactNode;
305
+ }
306
+ interface DescriptionProps extends React__default.HTMLAttributes<HTMLParagraphElement> {
307
+ children?: React__default.ReactNode;
308
+ }
309
+ interface ErrorMessageProps extends React__default.HTMLAttributes<HTMLParagraphElement> {
310
+ children?: React__default.ReactNode;
311
+ }
312
+ interface FormattedProps extends React__default.HTMLAttributes<HTMLSpanElement> {
313
+ render?: RenderProp;
314
+ }
315
+ declare const NumberField: {
316
+ Root: React__default.ForwardRefExoticComponent<NumberFieldRootProps & React__default.RefAttributes<HTMLDivElement>>;
317
+ Label: React__default.ForwardRefExoticComponent<LabelProps & React__default.RefAttributes<HTMLLabelElement>>;
318
+ Group: React__default.ForwardRefExoticComponent<GroupProps & React__default.RefAttributes<HTMLDivElement>>;
319
+ Input: React__default.ForwardRefExoticComponent<InputProps & React__default.RefAttributes<HTMLInputElement>>;
320
+ Increment: React__default.ForwardRefExoticComponent<IncrementProps & React__default.RefAttributes<HTMLButtonElement>>;
321
+ Decrement: React__default.ForwardRefExoticComponent<DecrementProps & React__default.RefAttributes<HTMLButtonElement>>;
322
+ HiddenInput: () => react_jsx_runtime.JSX.Element | null;
323
+ ScrubArea: React__default.ForwardRefExoticComponent<ScrubAreaProps & React__default.RefAttributes<HTMLSpanElement>>;
324
+ ScrubAreaCursor: React__default.ForwardRefExoticComponent<ScrubAreaCursorProps & React__default.RefAttributes<HTMLSpanElement>>;
325
+ Description: React__default.ForwardRefExoticComponent<DescriptionProps & React__default.RefAttributes<HTMLParagraphElement>>;
326
+ ErrorMessage: React__default.ForwardRefExoticComponent<ErrorMessageProps & React__default.RefAttributes<HTMLParagraphElement>>;
327
+ Formatted: React__default.ForwardRefExoticComponent<FormattedProps & React__default.RefAttributes<HTMLSpanElement>>;
328
+ };
329
+
330
+ interface NumberFieldContextValue {
331
+ state: NumberFieldState;
332
+ aria: NumberFieldAria;
333
+ inputRef: RefObject<HTMLInputElement | null>;
334
+ props: UseNumberFieldProps;
335
+ }
336
+ declare const NumberFieldContext: React$1.Context<NumberFieldContextValue | null>;
337
+ /**
338
+ * Hook for sub-components to access the NumberField context.
339
+ * Throws if used outside NumberField.Root.
340
+ */
341
+ declare function useNumberFieldContext(): NumberFieldContextValue;
342
+
343
+ export { type CaretBoundary as C, type DigitBlock as D, type FormatResult as F, type LocaleInfo as L, type NumberFieldState as N, type ParseResult as P, type RenderProp as R, type ScrubAreaOptions as S, type UseNumberFieldProps as U, type ChangeReason as a, NumberField as b, type NumberFieldAria as c, NumberFieldContext as d, type NumberFieldContextValue as e, type NumberFieldRootProps as f, type ScrubAreaCursorProps as g, type ScrubAreaProps as h, type StateRenderFn as i, type UseNumberFieldStateOptions as j, useNumberField as k, useNumberFieldContext as l, useNumberFieldFormat as m, useNumberFieldState as n, useControllableState as u };
@@ -0,0 +1,343 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React$1 from 'react';
3
+ import React__default, { RefObject } from 'react';
4
+
5
+ interface LocaleInfo {
6
+ /** Decimal separator for this locale (e.g. "." en-US, "," de-DE, "٫" fa-IR) */
7
+ decimalSeparator: string;
8
+ /** Grouping (thousands) separator (e.g. "," en-US, "." de-DE, "٬" fa-IR) */
9
+ groupingSeparator: string;
10
+ /** Minus sign character (usually "-" but can differ) */
11
+ minusSign: string;
12
+ /** Locale's representation of "0" (e.g. "0" for Latin, "۰" for Persian) */
13
+ zero: string;
14
+ /** Whether this is an RTL locale */
15
+ isRTL: boolean;
16
+ }
17
+ interface FormatResult {
18
+ formatted: string;
19
+ parts: Intl.NumberFormatPart[];
20
+ }
21
+ interface ParseResult {
22
+ /** The parsed number, or null if empty / un-parseable */
23
+ value: number | null;
24
+ /** True for valid numbers */
25
+ isValid: boolean;
26
+ /**
27
+ * True for valid-but-incomplete input that must not be reformatted yet:
28
+ * "-", "1.", "1.0", "1.00", etc.
29
+ */
30
+ isIntermediate: boolean;
31
+ }
32
+ /**
33
+ * boolean[] of length formattedValue.length + 1.
34
+ * true → cursor may rest at this index
35
+ * false → cursor must not rest here (e.g. inside a thousands separator)
36
+ */
37
+ type CaretBoundary = boolean[];
38
+ /** Unicode codepoint range [start, end] inclusive representing a digit block */
39
+ type DigitBlock = readonly [number, number];
40
+ interface UseNumberFieldStateOptions {
41
+ /** Controlled numeric value */
42
+ value?: number | null;
43
+ /** Uncontrolled default value */
44
+ defaultValue?: number | null;
45
+ /** Fires on every meaningful value change */
46
+ onChange?: (value: number | null) => void;
47
+ /** BCP 47 locale tag (default: browser locale) */
48
+ locale?: string;
49
+ /** Full Intl.NumberFormatOptions — currency, percent, decimal, etc. */
50
+ formatOptions?: Intl.NumberFormatOptions;
51
+ /** Minimum allowed value */
52
+ minValue?: number;
53
+ /** Maximum allowed value */
54
+ maxValue?: number;
55
+ /** Step amount for increment/decrement (default: 1) */
56
+ step?: number;
57
+ /** Large step — Shift+Arrow / PageUp/Down (default: step * 10) */
58
+ largeStep?: number;
59
+ /** Small step — Meta/Ctrl+Arrow (default: step * 0.1) */
60
+ smallStep?: number;
61
+ /** Allow negative values (default: true) */
62
+ allowNegative?: boolean;
63
+ /** Allow decimal values (default: true) */
64
+ allowDecimal?: boolean;
65
+ /** Override maximumFractionDigits from formatOptions */
66
+ maximumFractionDigits?: number;
67
+ /** Override minimumFractionDigits from formatOptions */
68
+ minimumFractionDigits?: number;
69
+ /** Always show exactly maximumFractionDigits decimal places */
70
+ fixedDecimalScale?: boolean;
71
+ /** When clamping happens (default: "blur") */
72
+ clampBehavior?: "blur" | "strict" | "none";
73
+ /** Apply live formatting while typing (default: true) */
74
+ liveFormat?: boolean;
75
+ /** Arbitrary prefix string (e.g. "$") */
76
+ prefix?: string;
77
+ /** Arbitrary suffix string (e.g. " تومان") */
78
+ suffix?: string;
79
+ /** Disable the field */
80
+ disabled?: boolean;
81
+ /** Make the field read-only */
82
+ readOnly?: boolean;
83
+ /** Mark the field as required */
84
+ required?: boolean;
85
+ /**
86
+ * Allow values outside min/max to be typed and committed without clamping.
87
+ * Useful when server-side validation handles clamping.
88
+ * When true, aria-invalid is set when value is out of range.
89
+ * default: false
90
+ */
91
+ allowOutOfRange?: boolean;
92
+ /**
93
+ * Custom validation function. Called on every value change.
94
+ * - Return `true` or `null`/`undefined` → valid
95
+ * - Return `false` → invalid (aria-invalid set, no error message)
96
+ * - Return a `string` → invalid with that string as the error message
97
+ */
98
+ validate?: (value: number | null) => boolean | string | null | undefined;
99
+ /**
100
+ * Fires with the raw unformatted string the user typed, preserving full
101
+ * decimal precision before JS float conversion. Useful for financial apps
102
+ * that need arbitrary-precision string arithmetic.
103
+ * Fires alongside `onChange`.
104
+ */
105
+ onRawChange?: (rawValue: string | null) => void;
106
+ /**
107
+ * Custom format function. When provided, replaces the built-in Intl.NumberFormat
108
+ * formatter for display purposes. Also used for initial display value.
109
+ */
110
+ formatValue?: (value: number) => string;
111
+ /**
112
+ * Custom parse function. When provided, replaces the built-in locale-aware parser.
113
+ * Must return `{ value: number | null, isIntermediate: boolean }`.
114
+ */
115
+ parseValue?: (input: string) => {
116
+ value: number | null;
117
+ isIntermediate: boolean;
118
+ };
119
+ }
120
+ interface NumberFieldState {
121
+ /** The display string shown in the input */
122
+ inputValue: string;
123
+ /** The parsed numeric value (null for empty/invalid) */
124
+ numberValue: number | null;
125
+ /**
126
+ * The raw string value exactly as the user typed it (before formatting).
127
+ * Preserves full decimal precision — useful for financial arbitrary-precision math.
128
+ */
129
+ rawValue: string | null;
130
+ /** Whether increment is currently possible */
131
+ canIncrement: boolean;
132
+ /** Whether decrement is currently possible */
133
+ canDecrement: boolean;
134
+ /** Whether the ScrubArea is currently being dragged */
135
+ isScrubbing: boolean;
136
+ /** Update the isScrubbing state (called by useScrubArea) */
137
+ setIsScrubbing: (val: boolean) => void;
138
+ /** Whether the input is currently focused */
139
+ isFocused: boolean;
140
+ /** Update the isFocused state (called by useNumberField) */
141
+ setIsFocused: (val: boolean) => void;
142
+ /** Current validation state — 'valid' if no validate prop, or based on validate result */
143
+ validationState: "valid" | "invalid";
144
+ /** Error message from validate() if it returned a string, otherwise null */
145
+ validationError: string | null;
146
+ /** Internal: set the reason for the next onChange call (used by useNumberField) */
147
+ _setLastChangeReason: (reason: ChangeReason) => void;
148
+ /** Internal: read the current change reason (used by NumberField.Root) */
149
+ _getLastChangeReason: () => ChangeReason;
150
+ /** Update display string (triggers parse + onChange) */
151
+ setInputValue: (val: string) => void;
152
+ /** Directly set the numeric value (triggers format + onChange) */
153
+ setNumberValue: (val: number | null) => void;
154
+ /** Format + clamp on blur — call from onBlur */
155
+ commit: () => void;
156
+ /** Increment by step */
157
+ increment: (amount?: number) => void;
158
+ /** Decrement by step */
159
+ decrement: (amount?: number) => void;
160
+ /** Jump to maxValue */
161
+ incrementToMax: () => void;
162
+ /** Jump to minValue */
163
+ decrementToMin: () => void;
164
+ /** Raw options (for hooks that need them) */
165
+ options: UseNumberFieldStateOptions;
166
+ }
167
+ /** Reason for a value change — propagated through onValueChange details */
168
+ type ChangeReason = "input" | "clear" | "blur" | "paste" | "keyboard" | "increment" | "decrement" | "wheel" | "scrub";
169
+ interface UseNumberFieldProps extends UseNumberFieldStateOptions {
170
+ /** Visible label text (used for aria-label fallback) */
171
+ label?: string;
172
+ "aria-label"?: string;
173
+ "aria-describedby"?: string;
174
+ "aria-labelledby"?: string;
175
+ /** Form field name — renders a hidden input */
176
+ name?: string;
177
+ /** id for the input element */
178
+ id?: string;
179
+ /** Enable mouse-wheel increment/decrement */
180
+ allowMouseWheel?: boolean;
181
+ /**
182
+ * Controls what is placed in the clipboard on copy/cut.
183
+ * - 'formatted' (default): browser-native copy of display string
184
+ * - 'raw': numberValue as a plain JS number string (e.g. "1234.56")
185
+ * - 'number': alias for 'raw'
186
+ */
187
+ copyBehavior?: "formatted" | "raw" | "number";
188
+ /** Milliseconds before press-and-hold repeat starts (default: 400) */
189
+ stepHoldDelay?: number;
190
+ /** Initial milliseconds between repeats during press-and-hold (default: 200) */
191
+ stepHoldInterval?: number;
192
+ onFocus?: (e: React.FocusEvent<HTMLInputElement>) => void;
193
+ onBlur?: (e: React.FocusEvent<HTMLInputElement>) => void;
194
+ }
195
+ interface NumberFieldAria {
196
+ labelProps: React.LabelHTMLAttributes<HTMLLabelElement>;
197
+ groupProps: React.HTMLAttributes<HTMLDivElement>;
198
+ inputProps: React.InputHTMLAttributes<HTMLInputElement>;
199
+ hiddenInputProps: React.InputHTMLAttributes<HTMLInputElement> | null;
200
+ incrementButtonProps: React.ButtonHTMLAttributes<HTMLButtonElement>;
201
+ decrementButtonProps: React.ButtonHTMLAttributes<HTMLButtonElement>;
202
+ descriptionProps: React.HTMLAttributes<HTMLElement>;
203
+ errorMessageProps: React.HTMLAttributes<HTMLElement>;
204
+ }
205
+ interface ScrubAreaOptions {
206
+ /**
207
+ * Axis to scrub on.
208
+ * - 'horizontal' (default): dragging right increments, left decrements
209
+ * - 'vertical': dragging up increments, down decrements
210
+ * - 'both': uses whichever axis has greater movement
211
+ */
212
+ direction?: "horizontal" | "vertical" | "both";
213
+ /** Pixels of drag movement required for one step (default: 4) */
214
+ pixelSensitivity?: number;
215
+ }
216
+ type StateRenderFn = (props: Record<string, unknown>, state: NumberFieldState) => React.ReactElement;
217
+ type RenderProp = React.ReactElement | StateRenderFn;
218
+ interface ScrubAreaProps extends ScrubAreaOptions, Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
219
+ render?: RenderProp;
220
+ children?: React.ReactNode;
221
+ }
222
+ interface ScrubAreaCursorProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
223
+ render?: RenderProp;
224
+ children?: React.ReactNode;
225
+ }
226
+ interface NumberFieldRootProps extends UseNumberFieldProps {
227
+ children?: React.ReactNode;
228
+ /** CSS class for the root wrapper div */
229
+ className?: string;
230
+ /** Inline style for the root wrapper div */
231
+ style?: React.CSSProperties;
232
+ /** Fires on every meaningful value change */
233
+ onValueChange?: (value: number | null, details: {
234
+ reason: ChangeReason;
235
+ formattedValue: string;
236
+ event?: React.SyntheticEvent;
237
+ }) => void;
238
+ /** Fires only on commit (blur, Enter) */
239
+ onValueCommitted?: (value: number | null, details: {
240
+ reason: "blur" | "keyboard";
241
+ }) => void;
242
+ }
243
+
244
+ declare function useNumberFieldState(options: UseNumberFieldStateOptions): NumberFieldState;
245
+
246
+ declare function useNumberField(props: UseNumberFieldProps, state: NumberFieldState, inputRef: React.RefObject<HTMLInputElement | null>): NumberFieldAria;
247
+
248
+ type FormatOptions = Pick<UseNumberFieldStateOptions, "locale" | "formatOptions" | "prefix" | "suffix" | "minimumFractionDigits" | "maximumFractionDigits" | "fixedDecimalScale">;
249
+ /**
250
+ * Lightweight display-only formatting hook. Returns the formatted string for
251
+ * a numeric value using the same Intl.NumberFormat engine as the full input.
252
+ *
253
+ * Use this when you need to display a formatted number in a read-only context
254
+ * (table cells, summaries, labels) without the overhead of a full input state machine.
255
+ *
256
+ * @example
257
+ * const price = useNumberFieldFormat(1234567.89, {
258
+ * locale: 'en-US',
259
+ * formatOptions: { style: 'currency', currency: 'USD' },
260
+ * })
261
+ * // price === "$1,234,567.89"
262
+ *
263
+ * @example
264
+ * const pct = useNumberFieldFormat(0.4267, {
265
+ * formatOptions: { style: 'percent', maximumFractionDigits: 1 },
266
+ * })
267
+ * // pct === "42.7%"
268
+ */
269
+ declare function useNumberFieldFormat(value: number | null, options?: FormatOptions): string;
270
+
271
+ interface UseControllableStateOptions<T> {
272
+ value?: T;
273
+ defaultValue?: T;
274
+ onChange?: (value: T) => void;
275
+ }
276
+ /**
277
+ * Manages controlled vs uncontrolled state.
278
+ * - If `value` is provided, the component is controlled.
279
+ * - Otherwise it manages its own state starting from `defaultValue`.
280
+ * Warns in dev mode if the component switches between controlled/uncontrolled.
281
+ */
282
+ declare function useControllableState<T>({ value, defaultValue, onChange, }: UseControllableStateOptions<T>): [
283
+ T | undefined,
284
+ (next: T | ((prev: T | undefined) => T)) => void
285
+ ];
286
+
287
+ interface LabelProps extends React__default.LabelHTMLAttributes<HTMLLabelElement> {
288
+ render?: RenderProp;
289
+ children?: React__default.ReactNode;
290
+ }
291
+ interface GroupProps extends React__default.HTMLAttributes<HTMLDivElement> {
292
+ render?: RenderProp;
293
+ children?: React__default.ReactNode;
294
+ }
295
+ interface InputProps extends Omit<React__default.InputHTMLAttributes<HTMLInputElement>, "type"> {
296
+ render?: RenderProp;
297
+ }
298
+ interface IncrementProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
299
+ render?: RenderProp;
300
+ children?: React__default.ReactNode;
301
+ }
302
+ interface DecrementProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
303
+ render?: RenderProp;
304
+ children?: React__default.ReactNode;
305
+ }
306
+ interface DescriptionProps extends React__default.HTMLAttributes<HTMLParagraphElement> {
307
+ children?: React__default.ReactNode;
308
+ }
309
+ interface ErrorMessageProps extends React__default.HTMLAttributes<HTMLParagraphElement> {
310
+ children?: React__default.ReactNode;
311
+ }
312
+ interface FormattedProps extends React__default.HTMLAttributes<HTMLSpanElement> {
313
+ render?: RenderProp;
314
+ }
315
+ declare const NumberField: {
316
+ Root: React__default.ForwardRefExoticComponent<NumberFieldRootProps & React__default.RefAttributes<HTMLDivElement>>;
317
+ Label: React__default.ForwardRefExoticComponent<LabelProps & React__default.RefAttributes<HTMLLabelElement>>;
318
+ Group: React__default.ForwardRefExoticComponent<GroupProps & React__default.RefAttributes<HTMLDivElement>>;
319
+ Input: React__default.ForwardRefExoticComponent<InputProps & React__default.RefAttributes<HTMLInputElement>>;
320
+ Increment: React__default.ForwardRefExoticComponent<IncrementProps & React__default.RefAttributes<HTMLButtonElement>>;
321
+ Decrement: React__default.ForwardRefExoticComponent<DecrementProps & React__default.RefAttributes<HTMLButtonElement>>;
322
+ HiddenInput: () => react_jsx_runtime.JSX.Element | null;
323
+ ScrubArea: React__default.ForwardRefExoticComponent<ScrubAreaProps & React__default.RefAttributes<HTMLSpanElement>>;
324
+ ScrubAreaCursor: React__default.ForwardRefExoticComponent<ScrubAreaCursorProps & React__default.RefAttributes<HTMLSpanElement>>;
325
+ Description: React__default.ForwardRefExoticComponent<DescriptionProps & React__default.RefAttributes<HTMLParagraphElement>>;
326
+ ErrorMessage: React__default.ForwardRefExoticComponent<ErrorMessageProps & React__default.RefAttributes<HTMLParagraphElement>>;
327
+ Formatted: React__default.ForwardRefExoticComponent<FormattedProps & React__default.RefAttributes<HTMLSpanElement>>;
328
+ };
329
+
330
+ interface NumberFieldContextValue {
331
+ state: NumberFieldState;
332
+ aria: NumberFieldAria;
333
+ inputRef: RefObject<HTMLInputElement | null>;
334
+ props: UseNumberFieldProps;
335
+ }
336
+ declare const NumberFieldContext: React$1.Context<NumberFieldContextValue | null>;
337
+ /**
338
+ * Hook for sub-components to access the NumberField context.
339
+ * Throws if used outside NumberField.Root.
340
+ */
341
+ declare function useNumberFieldContext(): NumberFieldContextValue;
342
+
343
+ export { type CaretBoundary as C, type DigitBlock as D, type FormatResult as F, type LocaleInfo as L, type NumberFieldState as N, type ParseResult as P, type RenderProp as R, type ScrubAreaOptions as S, type UseNumberFieldProps as U, type ChangeReason as a, NumberField as b, type NumberFieldAria as c, NumberFieldContext as d, type NumberFieldContextValue as e, type NumberFieldRootProps as f, type ScrubAreaCursorProps as g, type ScrubAreaProps as h, type StateRenderFn as i, type UseNumberFieldStateOptions as j, useNumberField as k, useNumberFieldContext as l, useNumberFieldFormat as m, useNumberFieldState as n, useControllableState as u };