raqam 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +1 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +1 -1
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react/useControllableState.ts","../src/core/formatter.ts","../src/core/normalizer.ts","../src/core/parser.ts","../src/react/useNumberFieldState.ts","../src/core/cursor.ts","../src/react/usePressAndHold.ts","../src/react/useNumberField.ts","../src/react/useNumberFieldFormat.ts","../src/react/context.ts","../src/react/useScrubArea.ts","../src/react/NumberField.tsx"],"names":["useControllableState","value","defaultValue","onChange","isControlled","wasControlled","useRef","internalValue","setInternalValue","useState","set","useCallback","next","nextValue","formatterCache","getFormatter","locale","options","key","fmt","extractLocaleInfo","styledFmt","probeFmt","parts","decimalSeparator","groupingSeparator","minusSign","zero","part","rtlLocales","resolvedLocale","isRTL","createFormatter","opts","intlOptions","intlFmt","cachedLocaleInfo","getLocaleInfo","formatToParts","result","format","formatted","formatResult","p","BUILTIN_DIGIT_BLOCKS","registeredBlocks","normalizeDigits","input","ch","code","start","end","digit","localizeDigits","base","d","isIntermediateStripped","stripped","allowDecimal","createParser","allowNegative","isPercent","currencySymbol","stripAffordances","raw","info","s","accountingMatch","negative","parse","n","isIntermediate","clamp","min","max","v","preciseAdd","a","b","factor","decimalPlaces","eIdx","exp","dotIdx","fracLen","idx","useNumberFieldState","formatOptions","minValue","maxValue","step","largeStep","smallStep","maximumFractionDigits","minimumFractionDigits","fixedDecimalScale","clampBehavior","prefix","suffix","allowOutOfRange","validate","onRawChange","customFormatValue","effMinFrac","effMaxFrac","effFixedScale","formatter","useMemo","parser","numberValue","setNumberValue","lastEmittedRef","formatDisplay","initialDisplay","inputValue","setInputValueRaw","lastFormattedRef","rawValue","setRawValueState","runValidation","val","initialValidation","initVal","validationState","setValidationState","validationError","setValidationError","isScrubbing","setIsScrubbing","isFocused","setIsFocused","lastChangeReasonRef","_setLastChangeReason","reason","_getLastChangeReason","externalValue","prevExternalValueRef","ev","finite","formatKey","prevFormatKeyRef","applyValidation","vs","ve","setInputValue","knownValue","setNumericValue","rawStr","commit","clamped","committed","reparsed","safeNumberValue","resolvedLargeStep","resolvedSmallStep","canIncrement","canDecrement","increment","amount","decrement","incrementToMax","decrementToMin","isAccepted","countAcceptedBefore","str","cursor","normalised","count","i","getCaretBoundary","formattedValue","len","boundary","computeNewCursorPosition","oldInput","oldCursor","newFormatted","inputType","acceptedCount","before","minusBeforeCaret","newHasMinus","normNew","pos","snapToBoundary","usePressAndHold","callback","delay","interval","disabled","callbackRef","useEffect","delayRef","intervalRef","delayTimerRef","repeatTimerRef","isHeldRef","clearTimers","scheduleRepeat","currentInterval","nextInterval","onPointerDown","e","onPointerUp","onPointerLeave","escapeRegex","parseSpecialNotation","t","m","mult","useNumberField","props","state","inputRef","allowMouseWheel","rawLiveFormat","name","readOnly","required","onFocus","onBlur","copyBehavior","stepHoldDelay","stepHoldInterval","customParseValue","onValueCommitted","notation","liveFormat","autoId","useId","inputId","labelId","descriptionId","errorId","isPercentStyle","liveMaxFrac","liveFormatter","formatGroupedFraction","source","decIdx","fracMatch","pendingCursor","useLayoutEffect","el","handler","isComposing","handleCompositionStart","handleCompositionEnd","composedValue","normalized","displayValue","handleChange","rawInputValue","cursorPos","_m","offset","rt","handlePaste","text","li","special","sval","localeInfo","allowedCharsPattern","stripped2","result2","handleCopy","handleCut","handleKeyDown","decPos","selEnd","currentValue","rawEdited","parseResult","nextDisplay","isDigitChar","isAffordanceChar","direction","handleBlur","handleFocus","incrementHold","decrementHold","ariaValueText","isInvalid","labelCountRef","hasLabel","setHasLabel","labelRef","node","ariaLabelledBy","labelProps","groupProps","inputProps","hiddenInputProps","incrementButtonProps","decrementButtonProps","useNumberFieldFormat","NumberFieldContext","createContext","useNumberFieldContext","ctx","useContext","useScrubArea","pixelSensitivity","setIsScrubbingLocal","stateRef","directionRef","sensitivityRef","isScrubbingRef","accumulatorRef","elementRef","virtualCursorRef","virtualCursor","setVirtualCursor","stableMouseMove","nx","ny","dir","delta","sensitivity","stablePointerLockChange","onKeyDown","cursorStyle","scrubAreaProps","renderWith","defaultElement","render","forwardedRef","baseProps","merged","React","REF_IN_PROPS","getElementRef","mergeRefs","refs","cleanups","ref","cleanup","stateDataAttrs","DIV_ONLY_KEYS","splitProps","fieldProps","divProps","Root","forwardRef","children","onValueChange","allProps","onValueChangeRef","wrappedProps","aria","jsx","Label","rest","renderRef","mergedRef","Group","Input","_ref","Increment","Decrement","HiddenInput","ScrubArea","ScrubAreaCursor","style","Description","ErrorMessage","content","Formatted","NumberField"],"mappings":"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","file":"react.js","sourcesContent":["import { useCallback, useRef, useState } from \"react\";\n\ninterface UseControllableStateOptions<T> {\n value?: T;\n defaultValue?: T;\n onChange?: (value: T) => void;\n}\n\n/**\n * Manages controlled vs uncontrolled state.\n * - If `value` is provided, the component is controlled.\n * - Otherwise it manages its own state starting from `defaultValue`.\n * Warns in dev mode if the component switches between controlled/uncontrolled.\n */\nexport function useControllableState<T>({\n value,\n defaultValue,\n onChange,\n}: UseControllableStateOptions<T>): [\n T | undefined,\n (next: T | ((prev: T | undefined) => T)) => void,\n] {\n const isControlled = value !== undefined;\n const wasControlled = useRef(isControlled);\n\n if (\n typeof window !== \"undefined\" &&\n (window as unknown as { __DEV__?: boolean }).__DEV__ !== false\n ) {\n if (wasControlled.current !== isControlled) {\n console.warn(\n `[raqam] Component is changing from ${\n wasControlled.current ? \"controlled\" : \"uncontrolled\"\n } to ${isControlled ? \"controlled\" : \"uncontrolled\"}. Decide between using a controlled or uncontrolled component and don't switch.`\n );\n }\n }\n\n const [internalValue, setInternalValue] = useState<T | undefined>(defaultValue);\n\n const set = useCallback(\n (next: T | ((prev: T | undefined) => T)) => {\n const nextValue =\n typeof next === \"function\"\n ? (next as (prev: T | undefined) => T)(isControlled ? value : internalValue)\n : next;\n\n if (!isControlled) {\n setInternalValue(nextValue);\n }\n onChange?.(nextValue);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [isControlled, value, internalValue, onChange]\n );\n\n return [isControlled ? value : internalValue, set];\n}\n","import type { FormatResult, LocaleInfo } from \"./types.js\";\n\n// ── Internal ──────────────────────────────────────────────────────────────────\n\n/** Probe value that will surface decimal AND grouping parts */\nconst PROBE_VALUE = 12345.6;\n\n/** Cache key = locale + JSON.stringify(options) */\nconst formatterCache = new Map<string, Intl.NumberFormat>();\n\nfunction getFormatter(\n locale: string | undefined,\n options: Intl.NumberFormatOptions | undefined\n): Intl.NumberFormat {\n const key = `${locale ?? \"\"}::${JSON.stringify(options ?? {})}`;\n let fmt = formatterCache.get(key);\n if (!fmt) {\n fmt = new Intl.NumberFormat(locale, options);\n formatterCache.set(key, fmt);\n }\n return fmt;\n}\n\n/** Extract locale meta from formatToParts — never hardcoded. */\nfunction extractLocaleInfo(\n locale: string | undefined,\n options: Intl.NumberFormatOptions | undefined\n): LocaleInfo {\n const styledFmt = getFormatter(locale, options);\n\n // Probe the separators with a NEUTRAL decimal formatter (same locale +\n // numbering system, but plain decimal style with a forced fraction). The\n // styled formatter can hide them — e.g. percent scales the probe so it has no\n // fraction (decimal separator invisible) and a positive value never yields a\n // minusSign. A negative, fractional decimal probe always surfaces all four.\n const probeFmt = getFormatter(locale, {\n minimumFractionDigits: 1,\n maximumFractionDigits: 1,\n numberingSystem: options?.numberingSystem,\n });\n const parts = probeFmt.formatToParts(-PROBE_VALUE);\n\n let decimalSeparator = \".\";\n let groupingSeparator = \",\";\n let minusSign = \"-\";\n let zero = \"0\";\n\n for (const part of parts) {\n if (part.type === \"decimal\") decimalSeparator = part.value;\n if (part.type === \"group\") groupingSeparator = part.value;\n if (part.type === \"minusSign\") minusSign = part.value;\n }\n\n // Detect locale zero digit\n for (const part of probeFmt.formatToParts(0)) {\n if (part.type === \"integer\") {\n zero = part.value;\n break;\n }\n }\n\n // RTL locales: Arabic / Hebrew / Persian / Urdu / Syriac etc.\n const rtlLocales = /^(ar|he|fa|ur|syc|nqo|ug|yi)/i;\n const resolvedLocale = styledFmt.resolvedOptions().locale;\n const isRTL = rtlLocales.test(resolvedLocale);\n\n return { decimalSeparator, groupingSeparator, minusSign, zero, isRTL };\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport interface FormatterOptions {\n locale?: string;\n formatOptions?: Intl.NumberFormatOptions;\n prefix?: string;\n suffix?: string;\n minimumFractionDigits?: number;\n maximumFractionDigits?: number;\n fixedDecimalScale?: boolean;\n}\n\nexport interface Formatter {\n format(value: number): string;\n formatToParts(value: number): Intl.NumberFormatPart[];\n getLocaleInfo(): LocaleInfo;\n formatResult(value: number): FormatResult;\n}\n\n/**\n * Create a formatter instance. Intl.NumberFormat is cached — safe to call\n * on every render.\n */\nexport function createFormatter(opts: FormatterOptions): Formatter {\n // Merge fraction digit overrides into formatOptions\n const intlOptions: Intl.NumberFormatOptions = { ...opts.formatOptions };\n\n if (opts.minimumFractionDigits !== undefined) {\n intlOptions.minimumFractionDigits = opts.minimumFractionDigits;\n }\n if (opts.maximumFractionDigits !== undefined) {\n intlOptions.maximumFractionDigits = opts.maximumFractionDigits;\n }\n if (opts.fixedDecimalScale && opts.maximumFractionDigits !== undefined) {\n intlOptions.minimumFractionDigits = opts.maximumFractionDigits;\n intlOptions.maximumFractionDigits = opts.maximumFractionDigits;\n }\n\n const intlFmt = getFormatter(opts.locale, intlOptions);\n // Lazy — computed once on first call\n let cachedLocaleInfo: LocaleInfo | null = null;\n\n function getLocaleInfo(): LocaleInfo {\n if (!cachedLocaleInfo) {\n cachedLocaleInfo = extractLocaleInfo(opts.locale, intlOptions);\n }\n return cachedLocaleInfo;\n }\n\n function formatToParts(value: number): Intl.NumberFormatPart[] {\n const parts = intlFmt.formatToParts(value);\n if (!opts.prefix && !opts.suffix) return parts;\n\n const result: Intl.NumberFormatPart[] = [];\n if (opts.prefix) result.push({ type: \"literal\", value: opts.prefix });\n result.push(...parts);\n if (opts.suffix) result.push({ type: \"literal\", value: opts.suffix });\n return result;\n }\n\n function format(value: number): string {\n if (!Number.isFinite(value)) return \"\";\n const formatted = intlFmt.format(value);\n return (opts.prefix ?? \"\") + formatted + (opts.suffix ?? \"\");\n }\n\n function formatResult(value: number): FormatResult {\n const parts = formatToParts(value);\n const formatted = parts.map((p) => p.value).join(\"\");\n return { formatted, parts };\n }\n\n return { format, formatToParts, getLocaleInfo, formatResult };\n}\n","import type { DigitBlock } from \"./types.js\";\n\n// ── Built-in digit blocks ────────────────────────────────────────────────────\n// These cover the digit systems required by the spec.\n// Additional blocks can be registered via registerLocale().\n\nconst BUILTIN_DIGIT_BLOCKS: DigitBlock[] = [\n [0x0660, 0x0669], // Arabic-Indic (arab)\n [0x06f0, 0x06f9], // Extended Arabic-Indic / Persian (arabext)\n [0x0966, 0x096f], // Devanagari / Hindi (deva)\n [0x09e6, 0x09ef], // Bengali (beng)\n [0x0e50, 0x0e59], // Thai (thai)\n];\n\n// Mutable registry — locale plugins can add blocks here\nconst registeredBlocks: DigitBlock[] = [...BUILTIN_DIGIT_BLOCKS];\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\nexport interface LocaleConfig {\n /** Extra digit block ranges to register */\n digitBlocks?: DigitBlock[];\n}\n\n/**\n * Register additional digit blocks (called by locale plugins as a side effect).\n * Duplicate ranges are silently ignored.\n */\nexport function registerLocale(config: LocaleConfig): void {\n if (!config.digitBlocks) return;\n for (const block of config.digitBlocks) {\n const already = registeredBlocks.some(([s]) => s === block[0]);\n if (!already) registeredBlocks.push(block);\n }\n}\n\n/**\n * Normalise any Unicode decimal digit in `input` to its ASCII equivalent (0–9).\n * Non-digit characters pass through unchanged.\n */\nexport function normalizeDigits(input: string): string {\n // Fast path: if there are no non-ASCII chars, return as-is\n if (!/[^\\u0020-\\u007e]/.test(input)) return input;\n\n return input.replace(/\\p{Nd}/gu, (ch) => {\n const code = ch.codePointAt(0)!;\n for (const [start, end] of registeredBlocks) {\n if (code >= start && code <= end) {\n return String(code - start);\n }\n }\n // Fallback: let JS try to parse it as a decimal digit\n const digit = Number.parseInt(ch, 10);\n return Number.isNaN(digit) ? ch : String(digit);\n });\n}\n\n/**\n * Inverse of {@link normalizeDigits}: map ASCII digits 0–9 to the locale's\n * native digit block (identified by its \"zero\" character). No-op when the\n * locale already uses ASCII digits. Used to keep intermediate (still-typing)\n * display strings in the user's native script.\n */\nexport function localizeDigits(input: string, zero: string): string {\n if (!zero || zero === \"0\") return input;\n const base = zero.codePointAt(0);\n if (base === undefined) return input;\n return input.replace(/[0-9]/g, (d) => String.fromCodePoint(base + (d.charCodeAt(0) - 48)));\n}\n\n/**\n * Returns true if the character is a non-Latin Unicode decimal digit\n * (i.e. would need normalization).\n */\nexport function isNonLatinDigit(ch: string): boolean {\n const code = ch.codePointAt(0);\n if (code === undefined) return false;\n if (code >= 0x30 && code <= 0x39) return false; // ASCII 0-9\n for (const [start, end] of registeredBlocks) {\n if (code >= start && code <= end) return true;\n }\n return false;\n}\n","import { createFormatter } from \"./formatter.js\";\nimport { normalizeDigits } from \"./normalizer.js\";\nimport type { LocaleInfo, ParseResult } from \"./types.js\";\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/**\n * Given an ASCII-normalised numeric string (`stripped` — digits, an optional\n * leading \"-\", and at most one \".\"), report whether it is a valid-but-incomplete\n * value that must NOT be reformatted while the user is still typing:\n * \"1.\" trailing decimal separator\n * \"1.0\" trailing zero after decimal\n * \"1.50\" trailing zeros after decimal\n * \".5\" leading decimal point (normalised to \"0.5\" only on blur)\n *\n * This runs on the *stripped* string, so grouping separators, prefixes,\n * suffixes and currency symbols never break the detection.\n */\nfunction isIntermediateStripped(stripped: string, allowDecimal: boolean): boolean {\n if (!allowDecimal) return false;\n if (/^-0+$/.test(stripped)) return true; // \"-0\" — user may still type \"-0.5\"\n if (/\\.$/.test(stripped)) return true; // \"1.\", \"-1.\"\n if (/\\.\\d*0$/.test(stripped)) return true; // \"1.0\", \"1.50\", \"1.230\"\n if (/^-?\\.\\d+$/.test(stripped)) return true; // \".5\", \"-.5\"\n return false;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport interface ParserOptions {\n locale?: string;\n formatOptions?: Intl.NumberFormatOptions;\n allowNegative?: boolean;\n allowDecimal?: boolean;\n prefix?: string;\n suffix?: string;\n}\n\nexport interface Parser {\n parse(input: string): ParseResult;\n isIntermediate(input: string): boolean;\n getLocaleInfo(): LocaleInfo;\n}\n\n/**\n * Create a locale-aware parser. Separator characters are extracted from\n * Intl.NumberFormat — never hardcoded.\n */\nexport function createParser(opts: ParserOptions = {}): Parser {\n const allowNegative = opts.allowNegative ?? true;\n const allowDecimal = opts.allowDecimal ?? true;\n // Percent fields hold the *fraction* (Intl multiplies by 100 on display), so\n // typed digits must be divided by 100: typing \"50\" means 50% i.e. value 0.5.\n const isPercent = opts.formatOptions?.style === \"percent\";\n\n // Re-use the formatter to get locale info\n const fmt = createFormatter({\n locale: opts.locale,\n formatOptions: opts.formatOptions,\n prefix: opts.prefix,\n suffix: opts.suffix,\n });\n\n // The literal currency symbol (e.g. \"$\", \"€\", or Arabic \"ج.م.\" which embeds\n // ASCII dots). Captured so it can be removed wholesale before separator\n // handling — otherwise its dots would be mistaken for a decimal point.\n let currencySymbol = \"\";\n if (opts.formatOptions?.style === \"currency\") {\n try {\n currencySymbol = fmt\n .formatToParts(1)\n .filter((p) => p.type === \"currency\")\n .map((p) => p.value)\n .join(\"\");\n } catch {\n currencySymbol = \"\";\n }\n }\n\n function getLocaleInfo(): LocaleInfo {\n return fmt.getLocaleInfo();\n }\n\n function stripAffordances(raw: string): string {\n const info = getLocaleInfo();\n\n // 1. Normalise non-Latin digits to ASCII\n let s = normalizeDigits(raw);\n\n // 1b. Remove the currency symbol wholesale (before separators are touched),\n // so a symbol containing ASCII dots — e.g. Arabic \"ج.م.\" — does not leave\n // stray \".\" that the numeric validation would reject.\n if (currencySymbol) {\n s = s.split(currencySymbol).join(\"\");\n }\n\n // 2. Accounting format: \"(1,234.56)\" or \"($1,234.56)\" → negative\n // Intl.NumberFormat with currencySign:\"accounting\" wraps negatives in parens\n const accountingMatch = s.match(/^\\((.+)\\)$/);\n if (accountingMatch) {\n s = `-${accountingMatch[1]}`;\n }\n\n // 3. Strip prefix / suffix\n if (opts.prefix && s.startsWith(opts.prefix)) {\n s = s.slice(opts.prefix.length);\n }\n if (opts.suffix && s.endsWith(opts.suffix)) {\n s = s.slice(0, -opts.suffix.length);\n }\n\n // 4. Strip grouping separators (escape special chars)\n if (info.groupingSeparator) {\n s = s.split(info.groupingSeparator).join(\"\");\n }\n\n // 5. Replace locale decimal separator with ASCII \".\"\n if (info.decimalSeparator !== \".\") {\n s = s.split(info.decimalSeparator).join(\".\");\n }\n\n // 6. Replace locale minus sign with ASCII \"-\"\n if (info.minusSign !== \"-\") {\n s = s.split(info.minusSign).join(\"-\");\n }\n // Also normalise the Unicode minus U+2212 (used by fa/sv/fi/nb… and often\n // pasted) so it is never stripped as a non-numeric character below.\n if (s.includes(\"−\")) {\n s = s.split(\"−\").join(\"-\");\n }\n\n // 7. Strip currency symbol, percent sign, spaces that Intl might prepend/append\n // Strip any remaining non-numeric chars except digits, \".\", \"-\"\n // (handles currency prefixes/suffixes from Intl)\n s = s.replace(/[^\\d.\\-]/g, \"\").trim();\n\n // 8. Collapse minus signs to a single leading one, so stray minuses typed in\n // the middle (\"1-23\") or doubled (\"--5\") never invalidate the whole value.\n if (s.includes(\"-\")) {\n const negative = s.startsWith(\"-\");\n s = s.replace(/-/g, \"\");\n if (negative) s = `-${s}`;\n }\n\n return s;\n }\n\n function parse(input: string): ParseResult {\n if (!input || input.trim() === \"\") {\n return { value: null, isValid: false, isIntermediate: false };\n }\n\n // Strip *first*, so intermediate detection never trips over grouping\n // separators, prefixes, suffixes or currency symbols.\n const stripped = stripAffordances(input);\n\n if (stripped === \"\") {\n return { value: null, isValid: false, isIntermediate: false };\n }\n\n // Lone minus — intermediate only if negatives are allowed.\n if (stripped === \"-\") {\n return { value: null, isValid: false, isIntermediate: allowNegative };\n }\n\n // Lone decimal point (\".\" or \"-.\") — intermediate only if decimals allowed.\n if (stripped === \".\" || stripped === \"-.\") {\n return {\n value: null,\n isValid: false,\n isIntermediate: allowDecimal && (stripped === \".\" || allowNegative),\n };\n }\n\n if (!allowNegative && stripped.startsWith(\"-\")) {\n return { value: null, isValid: false, isIntermediate: false };\n }\n\n if (!allowDecimal && stripped.includes(\".\")) {\n return { value: null, isValid: false, isIntermediate: false };\n }\n\n // Accept integers and decimals with the dot either trailing (\"1.\") or\n // leading (\".5\") so partially-typed values still yield a numeric value.\n if (!/^-?(?:\\d+\\.?\\d*|\\.\\d+)$/.test(stripped)) {\n return { value: null, isValid: false, isIntermediate: false };\n }\n\n let n = Number.parseFloat(stripped);\n if (!Number.isFinite(n)) {\n return { value: null, isValid: false, isIntermediate: false };\n }\n // Normalise negative zero so consumers never receive -0 from onChange.\n if (Object.is(n, -0)) n = 0;\n // Percent: divide by 100, snapping to canonical precision so the IEEE-754\n // division artifact (12.99/100 = 0.12990000000000002) never surfaces.\n if (isPercent && n !== 0) n = Number((n / 100).toPrecision(15));\n\n // A trailing-zero / trailing-dot / leading-dot value is still a real number\n // (so it is never wiped on blur) but must not be reformatted mid-typing.\n return {\n value: n,\n isValid: true,\n isIntermediate: isIntermediateStripped(stripped, allowDecimal),\n };\n }\n\n function isIntermediate(input: string): boolean {\n return parse(input).isIntermediate;\n }\n\n return { parse, isIntermediate, getLocaleInfo };\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\";\nimport { createFormatter } from \"../core/formatter.js\";\nimport { createParser } from \"../core/parser.js\";\nimport type { ChangeReason, NumberFieldState, UseNumberFieldStateOptions } from \"../core/types.js\";\nimport { useControllableState } from \"./useControllableState.js\";\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction clamp(value: number, min?: number, max?: number): number {\n let v = value;\n if (min !== undefined) v = Math.max(v, min);\n if (max !== undefined) v = Math.min(v, max);\n return v;\n}\n\nfunction preciseAdd(a: number, b: number): number {\n // Simple float precision fix — avoids 0.1 + 0.2 = 0.30000000000000004\n const precision = Math.max(decimalPlaces(a), decimalPlaces(b));\n const factor = 10 ** precision;\n return Math.round(a * factor + b * factor) / factor;\n}\n\nfunction decimalPlaces(n: number): number {\n if (!Number.isFinite(n)) return 0;\n const s = String(n);\n // Exponential form (e.g. \"1e-7\", \"1.5e-7\") — String() uses it below 1e-6.\n const eIdx = s.indexOf(\"e\");\n if (eIdx !== -1) {\n const exp = Number(s.slice(eIdx + 1));\n const dotIdx = s.indexOf(\".\");\n const fracLen = dotIdx === -1 ? 0 : eIdx - dotIdx - 1;\n return Math.max(0, fracLen - exp);\n }\n const idx = s.indexOf(\".\");\n return idx === -1 ? 0 : s.length - idx - 1;\n}\n\n// ── Hook ──────────────────────────────────────────────────────────────────────\n\nexport function useNumberFieldState(options: UseNumberFieldStateOptions): NumberFieldState {\n const {\n locale,\n formatOptions,\n minValue,\n maxValue,\n step = 1,\n largeStep,\n smallStep,\n allowNegative = true,\n allowDecimal = true,\n maximumFractionDigits,\n minimumFractionDigits,\n fixedDecimalScale,\n clampBehavior = \"blur\",\n prefix,\n suffix,\n allowOutOfRange = false,\n validate,\n onRawChange,\n formatValue: customFormatValue,\n } = options;\n\n // When decimals are disallowed, force the formatter to 0 fraction digits so\n // currency / fixedDecimalScale never pad \".00\" (which the dot-strip would then\n // re-read, exploding the value). See XF-2.\n const effMinFrac = allowDecimal ? minimumFractionDigits : 0;\n const effMaxFrac = allowDecimal ? maximumFractionDigits : 0;\n const effFixedScale = allowDecimal ? fixedDecimalScale : false;\n\n // ── Formatter & parser (re-created only when deps change) ──────────────────\n const formatter = useMemo(\n () =>\n createFormatter({\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits: effMinFrac,\n maximumFractionDigits: effMaxFrac,\n fixedDecimalScale: effFixedScale,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n locale,\n // JSON-serialize to detect object identity changes\n JSON.stringify(formatOptions),\n prefix,\n suffix,\n effMinFrac,\n effMaxFrac,\n effFixedScale,\n ]\n );\n\n const parser = useMemo(\n () =>\n createParser({\n locale,\n formatOptions,\n allowNegative,\n allowDecimal,\n prefix,\n suffix,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [locale, JSON.stringify(formatOptions), allowNegative, allowDecimal, prefix, suffix]\n );\n\n // ── Controlled/uncontrolled numeric value ──────────────────────────────────\n const [numberValue, setNumberValue] = useControllableState<number | null>({\n value: options.value,\n defaultValue: options.defaultValue ?? null,\n onChange: options.onChange,\n });\n\n // Last numeric value we emitted ourselves — used to tell our own onChange echo\n // apart from a genuine external controlled-value change (see sync block below).\n const lastEmittedRef = useRef<number | null | undefined>(\n options.value ?? options.defaultValue ?? null\n );\n\n // ── Display string ─────────────────────────────────────────────────────────\n // Stored in local state — can transiently diverge from numberValue\n // (e.g. while typing \"1.\" which isn't a valid JS number yet)\n const formatDisplay = useCallback(\n (n: number): string =>\n // Normalise -0 so it never renders as \"-0\" on any path (mount included).\n customFormatValue\n ? customFormatValue(Object.is(n, -0) ? 0 : n)\n : formatter.format(Object.is(n, -0) ? 0 : n),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [formatter, customFormatValue]\n );\n\n const initialDisplay = useMemo(() => {\n if (options.defaultValue != null) {\n return formatDisplay(options.defaultValue);\n }\n if (options.value != null) {\n return formatDisplay(options.value);\n }\n return \"\";\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []); // Only on mount\n\n const [inputValue, setInputValueRaw] = useState<string>(initialDisplay);\n\n // Track last formatted value so we can sync controlled value changes\n const lastFormattedRef = useRef<string>(initialDisplay);\n\n // ── Raw value (precision-preserving string) ────────────────────────────────\n const [rawValue, setRawValueState] = useState<string | null>(\n options.defaultValue != null ? String(options.defaultValue) : null\n );\n\n // ── Validation state ───────────────────────────────────────────────────────\n const runValidation = useCallback(\n (\n val: number | null\n ): { validationState: \"valid\" | \"invalid\"; validationError: string | null } => {\n if (!validate) return { validationState: \"valid\", validationError: null };\n const result = validate(val);\n if (result === false) return { validationState: \"invalid\", validationError: null };\n if (typeof result === \"string\")\n return { validationState: \"invalid\", validationError: result };\n return { validationState: \"valid\", validationError: null };\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [validate]\n );\n\n const initialValidation = useMemo(() => {\n const initVal = options.defaultValue ?? options.value ?? null;\n return runValidation(initVal != null ? initVal : null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []); // Only on mount\n\n const [validationState, setValidationState] = useState<\"valid\" | \"invalid\">(\n initialValidation.validationState\n );\n const [validationError, setValidationError] = useState<string | null>(\n initialValidation.validationError\n );\n\n // ── isScrubbing / isFocused state ──────────────────────────────────────────\n const [isScrubbing, setIsScrubbing] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n // ── Change reason ref (no re-render needed) ────────────────────────────────\n const lastChangeReasonRef = useRef<ChangeReason>(\"input\");\n const _setLastChangeReason = useCallback((reason: ChangeReason) => {\n lastChangeReasonRef.current = reason;\n }, []);\n\n const _getLastChangeReason = useCallback((): ChangeReason => {\n return lastChangeReasonRef.current;\n }, []);\n\n // ── Sync controlled value → display string when value changes externally ───\n // We must distinguish a *genuine* external change (parent set a new value,\n // form reset/prefill, etc.) from the echo of our own onChange. `lastEmittedRef`\n // tracks the value we last emitted; if the incoming controlled value differs\n // from it, the change came from outside and the display must be re-synced.\n const externalValue = options.value;\n const prevExternalValueRef = useRef(externalValue);\n // Object.is (not !==) so a controlled value of NaN compares equal to itself\n // and never triggers an unconditional render-phase setState → infinite loop.\n if (!Object.is(prevExternalValueRef.current, externalValue)) {\n prevExternalValueRef.current = externalValue;\n if (!Object.is(externalValue, lastEmittedRef.current)) {\n lastEmittedRef.current = externalValue;\n // Normalise -0 so a controlled value of -0 displays as \"0\", matching the\n // typed and commit paths.\n const ev = Object.is(externalValue, -0) ? 0 : externalValue;\n const finite = ev != null && Number.isFinite(ev);\n const formatted = finite ? formatDisplay(ev as number) : \"\";\n lastFormattedRef.current = formatted;\n setInputValueRaw(formatted);\n setRawValueState(finite ? String(ev) : null);\n }\n }\n\n // ── Reformat the display when locale / formatOptions change at runtime ──────\n // When the field is not being actively edited, a locale or format change must\n // re-render the existing value in the new format (e.g. switching en-US → de-DE).\n const formatKey = `${locale ?? \"\"}|${JSON.stringify(formatOptions ?? {})}|${prefix ?? \"\"}|${suffix ?? \"\"}|${effMinFrac ?? \"\"}|${effMaxFrac ?? \"\"}|${effFixedScale ?? \"\"}`;\n const prevFormatKeyRef = useRef(formatKey);\n if (prevFormatKeyRef.current !== formatKey) {\n prevFormatKeyRef.current = formatKey;\n if (numberValue != null && Number.isFinite(numberValue) && !isFocused) {\n const formatted = formatDisplay(numberValue);\n if (formatted !== inputValue) {\n setInputValueRaw(formatted);\n lastFormattedRef.current = formatted;\n }\n }\n }\n\n // ── Internal helper: apply validation after a value change ────────────────\n const applyValidation = useCallback(\n (val: number | null) => {\n const { validationState: vs, validationError: ve } = runValidation(val);\n setValidationState(vs);\n setValidationError(ve);\n },\n [runValidation]\n );\n\n // ── setInputValue ──────────────────────────────────────────────────────────\n // `knownValue` lets the caller supply the exact numeric value when `val` is a\n // formatted string the parser cannot faithfully reverse (compact \"2.5K\",\n // scientific, unit). Without it, the value is derived by parsing `val`.\n const setInputValue = useCallback(\n (val: string, knownValue?: number | null) => {\n const value = knownValue !== undefined ? knownValue : parser.parse(val).value;\n\n // Strict clamping: reject input that goes out of range (skipped when allowOutOfRange)\n if (clampBehavior === \"strict\" && !allowOutOfRange && value !== null) {\n if (minValue !== undefined && value < minValue) return;\n if (maxValue !== undefined && value > maxValue) return;\n }\n\n setInputValueRaw(val);\n lastEmittedRef.current = value;\n setNumberValue(value);\n // rawValue tracks what user typed, not the formatted output\n setRawValueState(value !== null ? val : null);\n onRawChange?.(value !== null ? val : null);\n applyValidation(value);\n },\n [\n parser,\n clampBehavior,\n allowOutOfRange,\n minValue,\n maxValue,\n setNumberValue,\n onRawChange,\n applyValidation,\n ]\n );\n\n // ── setNumberValue (external) ──────────────────────────────────────────────\n const setNumericValue = useCallback(\n (val: number | null) => {\n lastEmittedRef.current = val;\n setNumberValue(val);\n if (val != null) {\n const formatted = formatDisplay(val);\n setInputValueRaw(formatted);\n lastFormattedRef.current = formatted;\n const rawStr = String(val);\n setRawValueState(rawStr);\n onRawChange?.(rawStr);\n } else {\n setInputValueRaw(\"\");\n lastFormattedRef.current = \"\";\n setRawValueState(null);\n onRawChange?.(null);\n }\n applyValidation(val);\n },\n [formatDisplay, setNumberValue, onRawChange, applyValidation]\n );\n\n // ── commit (called on blur) ────────────────────────────────────────────────\n const commit = useCallback((): number | null => {\n if (numberValue == null) {\n setInputValueRaw(\"\");\n lastFormattedRef.current = \"\";\n return null;\n }\n\n let clamped = numberValue;\n // Clamp on blur, unless allowOutOfRange is true\n if (clampBehavior === \"blur\" && !allowOutOfRange) {\n clamped = clamp(numberValue, minValue, maxValue);\n }\n // Normalise negative zero so \"-0\" commits as plain \"0\"\n if (Object.is(clamped, -0)) clamped = 0;\n\n const formatted = formatDisplay(clamped);\n setInputValueRaw(formatted);\n lastFormattedRef.current = formatted;\n\n // Round the committed value to the displayed precision so the numeric value\n // never diverges from what is shown (e.g. a percent field that rounds the\n // live-typed fraction down to its configured scale on blur). Only adopt the\n // reparsed value when it round-trips exactly back to `formatted` — this skips\n // non-invertible notations (compact \"2.5K\", scientific, unit) and any custom\n // formatter whose output the parser cannot faithfully reverse.\n let committed = clamped;\n if (!customFormatValue) {\n const reparsed = parser.parse(formatted).value;\n if (reparsed !== null && Number.isFinite(reparsed) && formatDisplay(reparsed) === formatted) {\n committed = reparsed;\n }\n }\n\n if (committed !== numberValue) {\n lastEmittedRef.current = committed;\n setNumberValue(committed);\n }\n applyValidation(committed);\n return committed;\n }, [\n numberValue,\n clampBehavior,\n allowOutOfRange,\n minValue,\n maxValue,\n parser,\n formatDisplay,\n customFormatValue,\n setNumberValue,\n applyValidation,\n ]);\n\n // Treat a non-finite value (NaN/Infinity from a bad default/controlled value)\n // as empty so it never reaches ARIA, the hidden form input, or arithmetic.\n const safeNumberValue = numberValue != null && Number.isFinite(numberValue) ? numberValue : null;\n\n // ── Step computation ───────────────────────────────────────────────────────\n const resolvedLargeStep = largeStep ?? step * 10;\n const resolvedSmallStep = smallStep ?? step * 0.1;\n\n const canIncrement =\n !options.disabled &&\n !options.readOnly &&\n (allowOutOfRange ||\n maxValue === undefined ||\n (safeNumberValue ?? Number.NEGATIVE_INFINITY) < maxValue);\n\n const canDecrement =\n !options.disabled &&\n !options.readOnly &&\n (allowOutOfRange ||\n minValue === undefined ||\n (safeNumberValue ?? Number.POSITIVE_INFINITY) > minValue);\n\n const increment = useCallback(\n (amount?: number) => {\n const s = amount ?? step;\n const base = safeNumberValue ?? 0;\n const raw = preciseAdd(base, s);\n const next = allowOutOfRange ? raw : clamp(raw, minValue, maxValue);\n setNumericValue(next);\n },\n [safeNumberValue, step, minValue, maxValue, allowOutOfRange, setNumericValue]\n );\n\n const decrement = useCallback(\n (amount?: number) => {\n const s = amount ?? step;\n const base = safeNumberValue ?? 0;\n const raw = preciseAdd(base, -s);\n const next = allowOutOfRange ? raw : clamp(raw, minValue, maxValue);\n setNumericValue(next);\n },\n [safeNumberValue, step, minValue, maxValue, allowOutOfRange, setNumericValue]\n );\n\n const incrementToMax = useCallback(() => {\n if (maxValue !== undefined) setNumericValue(maxValue);\n }, [maxValue, setNumericValue]);\n\n const decrementToMin = useCallback(() => {\n if (minValue !== undefined) setNumericValue(minValue);\n }, [minValue, setNumericValue]);\n\n return {\n inputValue,\n numberValue: safeNumberValue,\n rawValue,\n canIncrement,\n canDecrement,\n isScrubbing,\n setIsScrubbing,\n isFocused,\n setIsFocused,\n validationState,\n validationError,\n _setLastChangeReason,\n _getLastChangeReason,\n setInputValue,\n setNumberValue: setNumericValue,\n commit,\n increment,\n decrement,\n incrementToMax,\n decrementToMin,\n options: {\n ...options,\n step,\n largeStep: resolvedLargeStep,\n smallStep: resolvedSmallStep,\n },\n };\n}\n","import { normalizeDigits } from \"./normalizer.js\";\nimport type { CaretBoundary, LocaleInfo } from \"./types.js\";\n\n// ── Accepted-character helpers ────────────────────────────────────────────────\n\n/**\n * Returns true if `ch` is an \"accepted\" character — one that the user typed\n * intentionally and that contributes to the numeric value:\n * - ASCII digit 0-9\n * - The locale decimal separator\n * - The locale minus sign\n */\nfunction isAccepted(ch: string, info: LocaleInfo): boolean {\n if (ch >= \"0\" && ch <= \"9\") return true;\n if (ch === info.decimalSeparator) return true;\n if (ch === info.minusSign || ch === \"-\") return true;\n // ASCII \".\" stands in for the decimal point in locales whose separator is\n // non-ASCII (ar/fa: ٫) — but not when \".\" is the grouping separator (de-DE).\n if (ch === \".\" && info.decimalSeparator !== \".\" && info.groupingSeparator !== \".\") return true;\n return false;\n}\n\n/**\n * Count how many \"accepted\" characters appear before position `cursor`\n * in `str` (after normalising non-Latin digits to ASCII).\n */\nfunction countAcceptedBefore(str: string, cursor: number, info: LocaleInfo): number {\n const normalised = normalizeDigits(str);\n let count = 0;\n for (let i = 0; i < cursor && i < normalised.length; i++) {\n if (isAccepted(normalised[i]!, info)) count++;\n }\n return count;\n}\n\n// ── Caret boundary ────────────────────────────────────────────────────────────\n\n/**\n * Build a boolean array of length `formattedValue.length + 1`.\n * `true` → cursor may rest at this position.\n * `false` → cursor must snap away (sits inside a formatting-only character\n * such as a grouping separator or a currency prefix).\n *\n * Rules:\n * - Start and end positions are always valid.\n * - A position immediately AFTER a grouping separator is invalid (the\n * cursor would look like it's between two digits but moving left would\n * skip the comma).\n * - A position immediately BEFORE a grouping separator is valid.\n */\nexport function getCaretBoundary(formattedValue: string, info: LocaleInfo): CaretBoundary {\n const len = formattedValue.length;\n const boundary: CaretBoundary = new Array(len + 1).fill(true) as boolean[];\n\n for (let i = 0; i < len; i++) {\n const ch = formattedValue[i]!;\n if (ch === info.groupingSeparator) {\n // Position immediately after the grouping separator is invalid\n boundary[i + 1] = false;\n }\n }\n\n // First and last are always valid\n boundary[0] = true;\n boundary[len] = true;\n\n return boundary;\n}\n\n// ── Cursor computation ────────────────────────────────────────────────────────\n\n/**\n * Compute the new cursor position in `newFormatted` that corresponds\n * semantically to `oldCursor` in `oldInput`.\n *\n * Algorithm (3 stages from the spec):\n *\n * 1. Count accepted characters before `oldCursor` in `oldInput`.\n * 2. Adjust for backspace-over-separator edge case.\n * 3. Walk `newFormatted` to find the position where the same count of\n * accepted chars precede it; snap to the nearest valid boundary.\n *\n * @param oldInput The raw string the user just typed into (pre-format)\n * @param oldCursor selectionStart captured from the native event\n * @param newFormatted The formatted string we're about to display\n * @param info Locale separators\n * @param inputType e.nativeEvent.inputType (optional — for backspace detection)\n */\nexport function computeNewCursorPosition(\n oldInput: string,\n oldCursor: number,\n newFormatted: string,\n info: LocaleInfo,\n inputType?: string\n): number {\n const normalised = normalizeDigits(oldInput);\n\n // Stage 1: count accepted chars before cursor in old input\n let acceptedCount = countAcceptedBefore(normalised, oldCursor, info);\n\n // Stage 1b: accounting/parens negatives drop the minus sign. If a minus was\n // counted before the caret but the reformatted output represents the sign\n // without one (e.g. \"($1.00)\"), the accepted-char counts are off by one —\n // correct for it so integer digits don't land inside the fraction.\n const before = oldInput.slice(0, oldCursor);\n const minusBeforeCaret = before.includes(\"-\") || before.includes(info.minusSign);\n const newHasMinus = newFormatted.includes(\"-\") || newFormatted.includes(info.minusSign);\n if (minusBeforeCaret && !newHasMinus) {\n acceptedCount = Math.max(0, acceptedCount - 1);\n }\n\n // Stage 2: backspace on grouping separator — also delete the preceding digit\n if (\n inputType === \"deleteContentBackward\" &&\n oldCursor > 0 &&\n oldInput[oldCursor - 1] === info.groupingSeparator\n ) {\n // The separator was deleted but we want to remove the preceding digit too\n acceptedCount = Math.max(0, acceptedCount - 1);\n }\n\n // Stage 3: build boundary and walk new formatted string\n const boundary = getCaretBoundary(newFormatted, info);\n const normNew = normalizeDigits(newFormatted);\n let count = 0;\n let pos = 0;\n\n for (let i = 0; i < normNew.length; i++) {\n if (count === acceptedCount) {\n pos = i;\n break;\n }\n if (isAccepted(normNew[i]!, info)) count++;\n pos = i + 1;\n }\n\n // If we ran through the entire string without reaching the target count,\n // place the cursor at the end. Note: acceptedCount === 0 means we correctly\n // want pos = 0 (set in the loop), so we must NOT override that case.\n if (acceptedCount > 0 && count < acceptedCount) {\n pos = newFormatted.length;\n }\n\n // Snap to nearest valid boundary\n pos = snapToBoundary(pos, boundary);\n\n return pos;\n}\n\n/**\n * If `pos` is at a false (invalid) boundary position, find the nearest\n * true position. Prefers moving forward; falls back to backward.\n */\nfunction snapToBoundary(pos: number, boundary: CaretBoundary): number {\n if (boundary[pos]) return pos;\n\n // Try forward first\n for (let i = pos + 1; i < boundary.length; i++) {\n if (boundary[i]) return i;\n }\n // Fall back to backward\n for (let i = pos - 1; i >= 0; i--) {\n if (boundary[i]) return i;\n }\n return 0;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef } from \"react\";\n\nexport interface UsePressAndHoldOptions {\n /** Milliseconds before repeating starts (default: 400) */\n delay?: number;\n /** Initial milliseconds between repeats — halves each tick, floors at 50 (default: 200) */\n interval?: number;\n /** Whether the element is disabled */\n disabled?: boolean;\n}\n\nexport interface PressAndHoldProps {\n onPointerDown: (e: React.PointerEvent) => void;\n onPointerUp: (e: React.PointerEvent) => void;\n onPointerLeave: (e: React.PointerEvent) => void;\n}\n\n/**\n * Returns pointer event handlers that call `callback` immediately on press,\n * then repeatedly with accelerating frequency while held down.\n *\n * Acceleration schedule (default settings):\n * immediate → 400ms wait → 200ms → 100ms → 50ms (floor, stays until release)\n *\n * All timing is handled via refs — zero state updates, zero re-renders.\n */\nexport function usePressAndHold(\n callback: () => void,\n options: UsePressAndHoldOptions = {}\n): PressAndHoldProps {\n const { delay = 400, interval = 200, disabled = false } = options;\n\n // Stable refs so handlers don't re-create on every render\n const callbackRef = useRef(callback);\n useEffect(() => {\n callbackRef.current = callback;\n });\n\n const delayRef = useRef(delay);\n useEffect(() => {\n delayRef.current = delay;\n });\n\n const intervalRef = useRef(interval);\n useEffect(() => {\n intervalRef.current = interval;\n });\n\n // Timer handle refs (null = no active timer)\n const delayTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const repeatTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const isHeldRef = useRef(false);\n\n const clearTimers = useCallback(() => {\n isHeldRef.current = false;\n if (delayTimerRef.current !== null) {\n clearTimeout(delayTimerRef.current);\n delayTimerRef.current = null;\n }\n if (repeatTimerRef.current !== null) {\n clearTimeout(repeatTimerRef.current);\n repeatTimerRef.current = null;\n }\n }, []);\n\n // Recursive accelerating repeat\n const scheduleRepeat = useCallback((currentInterval: number) => {\n if (!isHeldRef.current) return;\n callbackRef.current();\n const nextInterval = Math.max(50, Math.floor(currentInterval / 2));\n repeatTimerRef.current = setTimeout(() => {\n scheduleRepeat(nextInterval);\n }, currentInterval);\n }, []);\n\n const onPointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (disabled) return;\n // Only primary button (left mouse / single touch / pen)\n if (e.button !== 0 && e.pointerType === \"mouse\") return;\n\n // Fire immediately\n callbackRef.current();\n isHeldRef.current = true;\n\n // After initial delay, start accelerating repeats\n delayTimerRef.current = setTimeout(() => {\n scheduleRepeat(intervalRef.current);\n }, delayRef.current);\n },\n [disabled, scheduleRepeat]\n );\n\n const onPointerUp = useCallback(\n (e: React.PointerEvent) => {\n e.preventDefault();\n clearTimers();\n },\n [clearTimers]\n );\n\n const onPointerLeave = useCallback(\n (e: React.PointerEvent) => {\n void e;\n clearTimers();\n },\n [clearTimers]\n );\n\n // Safety: clear on unmount\n useEffect(() => clearTimers, [clearTimers]);\n\n return { onPointerDown, onPointerUp, onPointerLeave };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { computeNewCursorPosition } from \"../core/cursor.js\";\nimport { createFormatter } from \"../core/formatter.js\";\nimport { localizeDigits, normalizeDigits } from \"../core/normalizer.js\";\nimport { createParser } from \"../core/parser.js\";\nimport type { NumberFieldAria, NumberFieldState, UseNumberFieldProps } from \"../core/types.js\";\nimport { usePressAndHold } from \"./usePressAndHold.js\";\n\n// ── Tiny helper to safely escape regex special chars (including hyphen) ──────\n\nfunction escapeRegex(s: string): string {\n // Escaping hyphen prevents it from being misinterpreted as a range indicator\n // inside a character class (e.g. [.--] would be invalid without this)\n return s.replace(/[.*+?^${}()|[\\]\\\\\\-]/g, \"\\\\$&\");\n}\n\n/**\n * Parse scientific (\"1e3\", \"1.23E4\") and compact (\"1.5K\", \"3.4M\") notation that\n * the plain locale parser cannot handle. Used on paste so values copied from\n * spreadsheets / dashboards round-trip instead of being mangled by char-strip.\n * Returns null when `s` is not one of these forms.\n */\nfunction parseSpecialNotation(s: string): number | null {\n const t = s.replace(/\\s+/g, \"\");\n if (/^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)[eE][+-]?\\d+$/.test(t)) {\n const n = Number(t);\n return Number.isFinite(n) ? n : null;\n }\n const m = t.match(/^([+-]?(?:\\d+\\.?\\d*|\\.\\d+))(k|m|b|t|thousand|million|billion|trillion)$/i);\n if (m) {\n const mult: Record<string, number> = {\n k: 1e3,\n thousand: 1e3,\n m: 1e6,\n million: 1e6,\n b: 1e9,\n billion: 1e9,\n t: 1e12,\n trillion: 1e12,\n };\n const n = Number(m[1]) * mult[m[2].toLowerCase()]!;\n return Number.isFinite(n) ? n : null;\n }\n return null;\n}\n\nexport function useNumberField(\n props: UseNumberFieldProps,\n state: NumberFieldState,\n inputRef: React.RefObject<HTMLInputElement | null>\n): NumberFieldAria {\n const {\n locale,\n formatOptions,\n minValue,\n maxValue,\n allowNegative = true,\n allowDecimal = true,\n allowMouseWheel = false,\n liveFormat: rawLiveFormat = true,\n prefix,\n suffix,\n name,\n disabled,\n readOnly,\n required,\n onFocus,\n onBlur,\n maximumFractionDigits,\n minimumFractionDigits,\n fixedDecimalScale,\n copyBehavior = \"formatted\",\n stepHoldDelay = 400,\n stepHoldInterval = 200,\n formatValue: customFormatValue,\n parseValue: customParseValue,\n onValueCommitted,\n } = props; // formatValue/parseValue are on UseNumberFieldStateOptions (inherited)\n\n // Compact/scientific/engineering notation produce formatted strings (\"2.5K\",\n // \"1.5E3\") whose suffix/exponent characters collide with continued typing, so\n // we keep the raw typed digits live and only format on blur/commit.\n const notation = formatOptions?.notation;\n const liveFormat =\n rawLiveFormat &&\n notation !== \"compact\" &&\n notation !== \"scientific\" &&\n notation !== \"engineering\";\n\n const { step = 1, largeStep = step * 10, smallStep = step * 0.1 } = state.options;\n\n const autoId = useId();\n const inputId = props.id ?? `raqam-${autoId}`;\n const labelId = `${inputId}-label`;\n const descriptionId = `${inputId}-description`;\n const errorId = `${inputId}-error`;\n\n // ── Formatter & parser (kept in sync with state's) ──────────────────────\n // Mirror the state hook: drop fraction padding when decimals are disallowed.\n const effMinFrac = allowDecimal ? minimumFractionDigits : 0;\n const effMaxFrac = allowDecimal ? maximumFractionDigits : 0;\n const effFixedScale = allowDecimal ? fixedDecimalScale : false;\n\n const formatter = useMemo(\n () =>\n createFormatter({\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits: effMinFrac,\n maximumFractionDigits: effMaxFrac,\n fixedDecimalScale: effFixedScale,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [locale, JSON.stringify(formatOptions), prefix, suffix, effMinFrac, effMaxFrac, effFixedScale]\n );\n\n // Live-typing formatter: keeps grouping + currency symbol but drops the\n // minimum-fraction *padding* (\".00\") so currency / fixedDecimalScale fields\n // group correctly while typing and never accumulate padding zeros. The full\n // `formatter` (with padding) is applied on commit/blur.\n //\n // Percent fields default to maximumFractionDigits:0, which would round away\n // the fraction the user is typing (\"12.5\" → \"13%\") and — because the rounded\n // string is shorter — corrupt the next keystroke. Give the percent live\n // formatter room so typing never rounds; commit() rounds to the real scale.\n const isPercentStyle = formatOptions?.style === \"percent\";\n const liveMaxFrac = allowDecimal ? (isPercentStyle ? 20 : effMaxFrac) : 0;\n const liveFormatter = useMemo(\n () =>\n createFormatter({\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits: 0,\n maximumFractionDigits: liveMaxFrac,\n fixedDecimalScale: false,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [locale, JSON.stringify(formatOptions), prefix, suffix, liveMaxFrac]\n );\n\n const parser = useMemo(\n () =>\n createParser({\n locale,\n formatOptions,\n allowNegative,\n allowDecimal,\n prefix,\n suffix,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [locale, JSON.stringify(formatOptions), allowNegative, allowDecimal, prefix, suffix]\n );\n\n // Re-format `value` so its integer part groups while the EXACT typed fraction\n // (incl. trailing zeros) from `source` is preserved. Returns null when there is\n // no integer part (leading-dot \".5\" — keep it raw to avoid a \"0\" prepend that\n // would shift the caret) or no fraction (trailing dot). Used by the typing path\n // and the grouping-comma / trailing-affordance backspace paths so they all\n // preserve typed trailing zeros consistently.\n const formatGroupedFraction = useCallback(\n (value: number, source: string): string | null => {\n const info = formatter.getLocaleInfo();\n let decIdx = source.lastIndexOf(info.decimalSeparator);\n // Fall back to an ASCII \".\" only when it stands in for the decimal point\n // (not when \".\" is the grouping separator, e.g. de-DE — see Fix J).\n if (decIdx === -1 && info.decimalSeparator !== \".\" && info.groupingSeparator !== \".\") {\n decIdx = source.lastIndexOf(\".\");\n }\n if (decIdx === -1) return null;\n if (!/\\d/.test(normalizeDigits(source.slice(0, decIdx)))) return null; // leading dot\n const fracMatch = normalizeDigits(source.slice(decIdx + 1)).match(/^\\d+/);\n if (!fracMatch) return null; // trailing dot\n const fracLen = Math.min(fracMatch[0].length, effMaxFrac ?? 20, 20);\n if (fracLen === 0) return null;\n return createFormatter({\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits: fracLen,\n maximumFractionDigits: fracLen,\n }).format(value);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [formatter, locale, JSON.stringify(formatOptions), prefix, suffix, effMaxFrac]\n );\n\n // ── Cursor engine ────────────────────────────────────────────────────────\n const pendingCursor = useRef<number | null>(null);\n\n // Restore cursor synchronously after React commits the new value to DOM\n useLayoutEffect(() => {\n if (\n pendingCursor.current !== null &&\n inputRef.current &&\n document.activeElement === inputRef.current\n ) {\n inputRef.current.setSelectionRange(pendingCursor.current, pendingCursor.current);\n pendingCursor.current = null;\n }\n // Run after every inputValue change\n }, [state.inputValue, inputRef]);\n\n // ── Mouse wheel (non-passive native listener) ────────────────────────────\n // React's synthetic onWheel is passive in React 17+; it cannot call\n // preventDefault(). We must attach a native, non-passive listener instead.\n useEffect(() => {\n const el = inputRef.current;\n if (!el || !allowMouseWheel) return;\n\n const handler = (e: WheelEvent) => {\n if (disabled || readOnly) return;\n if (document.activeElement !== el) return;\n e.preventDefault();\n state._setLastChangeReason(\"wheel\");\n if (e.deltaY < 0) {\n state.increment();\n } else {\n state.decrement();\n }\n };\n\n el.addEventListener(\"wheel\", handler, { passive: false });\n return () => el.removeEventListener(\"wheel\", handler);\n }, [allowMouseWheel, disabled, readOnly, state, inputRef]);\n\n // ── IME Composition state ────────────────────────────────────────────────\n // During CJK IME input, partial composed characters must not trigger live\n // formatting. We suspend formatting during composition and resume on end.\n const isComposing = useRef(false);\n\n const handleCompositionStart = useCallback(() => {\n isComposing.current = true;\n }, []);\n\n const handleCompositionEnd = useCallback(\n (e: React.CompositionEvent<HTMLInputElement>) => {\n isComposing.current = false;\n // After composition ends, run the full format cycle on the composed value\n const composedValue = e.currentTarget.value;\n const info = formatter.getLocaleInfo();\n const normalized = normalizeDigits(composedValue);\n\n let displayValue: string;\n if (customParseValue) {\n const result = customParseValue(normalized);\n if (result.isIntermediate) {\n displayValue = normalized;\n } else if (result.value !== null && customFormatValue) {\n displayValue = customFormatValue(result.value);\n } else if (result.value !== null) {\n displayValue = formatter.format(result.value);\n } else {\n displayValue = normalized;\n }\n // Disable cursor engine for custom format/parse\n pendingCursor.current = displayValue.length;\n } else if (liveFormat) {\n const result = parser.parse(normalized);\n if (result.isIntermediate) {\n // Keep the still-typing display in the locale's native digit script.\n displayValue = localizeDigits(normalized, info.zero);\n } else if (result.value !== null) {\n displayValue = customFormatValue\n ? customFormatValue(result.value)\n : liveFormatter.format(result.value);\n } else {\n displayValue = normalized === \"\" ? \"\" : normalized;\n }\n pendingCursor.current = computeNewCursorPosition(\n composedValue,\n composedValue.length,\n displayValue,\n info,\n \"insertCompositionText\"\n );\n } else {\n displayValue = normalized;\n pendingCursor.current = normalized.length;\n }\n\n state._setLastChangeReason(\"input\");\n state.setInputValue(displayValue);\n },\n [formatter, liveFormatter, parser, liveFormat, state, customFormatValue, customParseValue]\n );\n\n // ── onChange handler ─────────────────────────────────────────────────────\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const rawInputValue = e.target.value;\n const cursorPos = e.target.selectionStart ?? rawInputValue.length;\n const inputType = (e.nativeEvent as InputEvent).inputType;\n const info = formatter.getLocaleInfo();\n\n // During IME composition, skip live formatting — just track the raw value\n if (isComposing.current) {\n state.setInputValue(rawInputValue);\n return;\n }\n\n // Normalise non-Latin digits\n let normalized = normalizeDigits(rawInputValue);\n\n // Drop characters disallowed by the constraint flags *live*, so the field\n // never shows an invalid string that gets wiped on blur. The minus / dot\n // keys simply do nothing instead of poisoning the value.\n if (!allowNegative) {\n normalized = normalized.split(\"-\").join(\"\").split(info.minusSign).join(\"\");\n }\n if (!allowDecimal) {\n normalized = normalized.split(\".\").join(\"\").split(info.decimalSeparator).join(\"\");\n } else if (info.decimalSeparator !== \".\" && info.groupingSeparator !== \".\") {\n // Latin-keyboard users type the ASCII \".\" as the decimal point even in\n // locales whose separator is non-ASCII (ar/fa: ٫). Map a \".\" that is part\n // of a number (adjacent to a digit) onto the locale separator so the value\n // parses and the caret engine (which only tracks the locale separator)\n // doesn't strand the dot. Dots inside a symbol (e.g. the Arabic currency\n // symbol \"ج.م.\") are NOT adjacent to digits, so they stay untouched.\n // Skipped entirely when \".\" is the grouping separator (e.g. de-DE).\n normalized = normalized.replace(/\\./g, (_m, offset: number, str: string) =>\n /\\d/.test(str[offset - 1] ?? \"\") || /\\d/.test(str[offset + 1] ?? \"\")\n ? info.decimalSeparator\n : \".\"\n );\n }\n\n let displayValue: string;\n let knownValue: number | null | undefined;\n\n // Custom parse/format escape hatch\n if (customParseValue) {\n const result = customParseValue(normalized);\n if (result.isIntermediate) {\n displayValue = normalized;\n } else if (result.value !== null) {\n displayValue = customFormatValue\n ? customFormatValue(result.value)\n : formatter.format(result.value);\n } else if (normalized === \"\") {\n displayValue = \"\";\n } else {\n displayValue = normalized;\n }\n // Can't predict cursor position with custom formatter — place at end\n pendingCursor.current = displayValue.length;\n } else if (liveFormat) {\n const result = parser.parse(normalized);\n\n if (result.isIntermediate) {\n // A trailing-zero decimal (e.g. \"12.50\") is intermediate, but its\n // integer part should still group live (insert \"99\" into \"$12.50\" must\n // show \"$9,912.50\"). Re-format preserving the typed fraction; lone \"-\",\n // trailing \".\" and leading \".\" keep the raw form.\n const grouped =\n !customFormatValue && result.value !== null\n ? formatGroupedFraction(result.value, normalized)\n : null;\n displayValue = grouped ?? localizeDigits(normalized, info.zero);\n } else if (result.value !== null) {\n if (customFormatValue) {\n displayValue = customFormatValue(result.value);\n } else {\n displayValue = liveFormatter.format(result.value);\n // The display will be re-parsed by setInputValue. For invertible\n // formats that round-trips (and rounds the value to the displayed\n // precision); for non-invertible notation (compact \"2.5K\",\n // scientific, unit) re-parsing destroys magnitude — so pass the\n // exact typed value through when the format does not round-trip.\n const rt = parser.parse(displayValue).value;\n knownValue =\n rt !== null && Number.isFinite(rt) && liveFormatter.format(rt) === displayValue\n ? rt\n : result.value;\n }\n } else if (normalized === \"\" || !/\\d/.test(normalized)) {\n // Empty, or only formatting affordances left (a lone \"%\", suffix, etc.\n // after deleting the last digit) — clear the field instead of stranding\n // the orphaned characters.\n displayValue = \"\";\n } else {\n // Invalid input — keep the raw normalised string so the user can\n // see what they typed (they'll get corrected on blur)\n displayValue = normalized;\n }\n\n if (customFormatValue) {\n // Custom format: can't predict cursor, place at end\n pendingCursor.current = displayValue.length;\n } else {\n // Compute and stash cursor position for useLayoutEffect\n pendingCursor.current = computeNewCursorPosition(\n rawInputValue,\n cursorPos,\n displayValue,\n info,\n inputType\n );\n }\n } else {\n // No live format — just pass through normalised digits\n displayValue = normalized;\n pendingCursor.current = cursorPos;\n }\n\n // An edit that empties the field reports the dedicated \"clear\" reason so\n // consumers can distinguish a deletion-to-empty from ordinary typing.\n state._setLastChangeReason(displayValue === \"\" ? \"clear\" : \"input\");\n state.setInputValue(displayValue, knownValue);\n },\n [\n formatter,\n liveFormatter,\n parser,\n liveFormat,\n state,\n customFormatValue,\n customParseValue,\n formatGroupedFraction,\n ]\n );\n\n // ── Paste handler ────────────────────────────────────────────────────────\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n const text = e.clipboardData.getData(\"text/plain\");\n if (!text) return;\n\n // 1. Strip common currency symbols (global currencies)\n const stripped = text.replace(/[€$£¥₹₺₽﷼฿₩¢₦₨₪₫₱]/g, \"\").trim();\n\n // 2. Normalize non-Latin digits to ASCII\n let normalized = normalizeDigits(stripped);\n\n // Honour the constraint flags on paste too (drop minus / decimal).\n if (!allowNegative) {\n const li = formatter.getLocaleInfo();\n normalized = normalized.split(\"-\").join(\"\").split(li.minusSign).join(\"\");\n }\n if (!allowDecimal) {\n const li = formatter.getLocaleInfo();\n normalized = normalized.split(\".\").join(\"\").split(li.decimalSeparator).join(\"\");\n }\n\n state._setLastChangeReason(\"paste\");\n\n // Custom parse escape hatch\n if (customParseValue) {\n const result = customParseValue(normalized);\n if (result.value !== null) {\n const formatted = customFormatValue\n ? customFormatValue(result.value)\n : formatter.format(result.value);\n // Pass the known value so a non-invertible format (compact/scientific)\n // is not re-parsed into a wrong magnitude.\n state.setInputValue(formatted, result.value);\n pendingCursor.current = formatted.length;\n }\n return;\n }\n\n // 2.5 Scientific / compact notation (1e3, 1.23E4, 1.5K…) before the\n // locale parser, whose char-strip would otherwise mangle the e / K.\n const special = parseSpecialNotation(normalized);\n if (special !== null) {\n const isPercent = formatOptions?.style === \"percent\";\n const sval = isPercent ? special / 100 : special;\n const formatted = customFormatValue ? customFormatValue(sval) : formatter.format(sval);\n state.setInputValue(formatted, sval);\n pendingCursor.current = formatted.length;\n return;\n }\n\n // 3. Try parse with current locale parser\n const result = parser.parse(normalized);\n\n if (result.value !== null) {\n const formatted = formatter.format(result.value);\n state.setInputValue(formatted, result.value);\n pendingCursor.current = formatted.length;\n return;\n }\n\n // 4. Fallback: strip everything except digits, locale decimal, minus sign\n const localeInfo = formatter.getLocaleInfo();\n const allowedCharsPattern = new RegExp(\n `[^0-9${escapeRegex(localeInfo.decimalSeparator)}${escapeRegex(localeInfo.minusSign)}-]`,\n \"g\"\n );\n const stripped2 = normalized.replace(allowedCharsPattern, \"\");\n const result2 = parser.parse(stripped2);\n\n if (result2.value !== null) {\n const formatted = formatter.format(result2.value);\n state.setInputValue(formatted, result2.value);\n pendingCursor.current = formatted.length;\n }\n // If still invalid, silently discard — don't paste garbage into the field\n },\n [parser, formatter, state, customFormatValue, customParseValue]\n );\n\n // ── Copy / Cut handlers ──────────────────────────────────────────────────\n const handleCopy = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n if (copyBehavior === \"formatted\") return; // browser handles it natively\n\n e.preventDefault();\n const text = String(state.numberValue ?? \"\");\n e.clipboardData.setData(\"text/plain\", text);\n },\n [copyBehavior, state.numberValue]\n );\n\n const handleCut = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n if (copyBehavior === \"formatted\") return; // browser handles it\n\n e.preventDefault();\n const text = String(state.numberValue ?? \"\");\n e.clipboardData.setData(\"text/plain\", text);\n // Clear the field after cut — report the dedicated \"clear\" reason.\n state._setLastChangeReason(\"clear\");\n state.setInputValue(\"\");\n },\n [copyBehavior, state]\n );\n\n // ── Keyboard handler ─────────────────────────────────────────────────────\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (disabled || readOnly) return;\n\n const key = e.key;\n\n // Smart backspace: when cursor is immediately after a grouping separator\n // (no selection active, no modifier keys), delete both the separator and\n // the preceding digit so the user can backspace through formatted numbers\n // without the comma \"blocking\" deletion.\n //\n // This must be handled in keydown — by the time onChange fires, the\n // browser has already removed the separator character, making it\n // impossible to detect what was deleted.\n // Smart decimal: when the user types the decimal separator but one already\n // exists in the formatted value (e.g. \"1.00\" with fixedDecimalScale),\n // move the cursor to just after the decimal separator instead of inserting\n // a duplicate. This enables the financial UX pattern:\n // \"1.00\" → type \".\" → cursor jumps after \".\" → type \"5\" → \"1.50\"\n // Same applies for negative values: \"-1.00\" → type \".\" → cursor after \".\"\n if (!e.metaKey && !e.ctrlKey && !e.altKey && allowDecimal) {\n const localeInfo = formatter.getLocaleInfo();\n // Match the locale's decimal separator key (e.g. \".\" for en-US, \",\" for\n // de-DE), plus the ASCII \".\" when it stands in for a non-ASCII separator\n // (ar/fa). Do NOT match \".\" when it is the grouping separator (de-DE).\n const isDecimalKey =\n key === localeInfo.decimalSeparator ||\n (key === \".\" &&\n localeInfo.decimalSeparator !== \".\" &&\n localeInfo.groupingSeparator !== \".\");\n if (isDecimalKey) {\n const input = inputRef.current;\n if (input) {\n const decPos = input.value.indexOf(localeInfo.decimalSeparator);\n if (decPos !== -1) {\n e.preventDefault();\n input.setSelectionRange(decPos + 1, decPos + 1);\n return;\n }\n }\n }\n }\n\n if (key === \"Backspace\" && !e.shiftKey && !e.altKey && !e.metaKey && !e.ctrlKey) {\n const input = inputRef.current;\n if (input) {\n const cursor = input.selectionStart ?? 0;\n const selEnd = input.selectionEnd ?? cursor;\n const currentValue = input.value;\n const info = formatter.getLocaleInfo();\n\n if (\n cursor === selEnd && // no text selection — single caret\n cursor >= 2 &&\n currentValue[cursor - 1] === info.groupingSeparator\n ) {\n e.preventDefault();\n // Remove the grouping separator (cursor-1) AND the digit before it (cursor-2)\n const rawEdited = currentValue.slice(0, cursor - 2) + currentValue.slice(cursor);\n const parseResult = parser.parse(rawEdited);\n\n state._setLastChangeReason(\"input\");\n let nextDisplay: string;\n if (parseResult.value !== null) {\n // Preserve typed trailing zeros; use the LIVE formatter (no\n // min-fraction padding) so editing matches the typing display.\n nextDisplay =\n formatGroupedFraction(parseResult.value, rawEdited) ??\n liveFormatter.format(parseResult.value);\n state.setInputValue(nextDisplay, parseResult.value);\n } else {\n // Empty or intermediate — store as-is (blur will clean up). If the\n // edit emptied the field, report the dedicated \"clear\" reason.\n nextDisplay = rawEdited;\n if (rawEdited === \"\") state._setLastChangeReason(\"clear\");\n state.setInputValue(rawEdited);\n }\n // Remap the caret through the cursor engine so re-grouping shifts\n // (e.g. \"1,234,567\" → \"123,567\") never leave it stranded after a comma.\n pendingCursor.current = computeNewCursorPosition(\n rawEdited,\n cursor - 2,\n nextDisplay,\n info,\n \"deleteContentBackward\"\n );\n return;\n }\n\n // Backspace over a trailing affordance (% sign, suffix like \" kg\") —\n // the browser would delete the affordance char, but the formatter\n // immediately re-appends it, so the field never changes. Instead delete\n // the digit that precedes the affordance run. Digit detection is\n // script-aware (\\p{Nd}) so it works for native digits (fa/ar) too.\n const isDigitChar = (ch: string | undefined): boolean =>\n ch !== undefined && /\\p{Nd}/u.test(ch);\n const isAffordanceChar = (ch: string | undefined): boolean =>\n ch !== undefined &&\n !isDigitChar(ch) &&\n ch !== info.decimalSeparator &&\n ch !== info.minusSign &&\n ch !== \"-\";\n if (\n cursor === selEnd &&\n cursor === currentValue.length &&\n cursor >= 1 &&\n isAffordanceChar(currentValue[cursor - 1])\n ) {\n // Walk back over the trailing affordance run to the last real char.\n let i = cursor;\n while (i > 0 && isAffordanceChar(currentValue[i - 1])) i--;\n if (i > 0 && isDigitChar(currentValue[i - 1])) {\n e.preventDefault();\n const rawEdited = currentValue.slice(0, i - 1) + currentValue.slice(i);\n const parseResult = parser.parse(rawEdited);\n state._setLastChangeReason(\"input\");\n let nextDisplay: string;\n if (parseResult.value !== null && /\\p{Nd}/u.test(rawEdited)) {\n // Use the LIVE formatter (no min-fraction padding) so the display\n // matches the typing path — never re-pad \".00\" mid-edit.\n nextDisplay =\n formatGroupedFraction(parseResult.value, rawEdited) ??\n liveFormatter.format(parseResult.value);\n state.setInputValue(nextDisplay, parseResult.value);\n } else {\n // No digits left — clear the field (don't strand the affordance).\n // Report the dedicated \"clear\" reason like the onChange path.\n nextDisplay = \"\";\n state._setLastChangeReason(\"clear\");\n state.setInputValue(\"\");\n }\n pendingCursor.current = computeNewCursorPosition(\n rawEdited,\n i - 1,\n nextDisplay,\n info,\n \"deleteContentBackward\"\n );\n return;\n }\n }\n }\n }\n\n if (key === \"ArrowUp\" || key === \"ArrowDown\") {\n e.preventDefault();\n const direction = key === \"ArrowUp\" ? 1 : -1;\n state._setLastChangeReason(\"keyboard\");\n if (e.shiftKey) {\n direction > 0 ? state.increment(largeStep) : state.decrement(largeStep);\n } else if (e.metaKey || e.ctrlKey) {\n direction > 0 ? state.increment(smallStep) : state.decrement(smallStep);\n } else {\n direction > 0 ? state.increment() : state.decrement();\n }\n return;\n }\n\n if (key === \"PageUp\") {\n e.preventDefault();\n state._setLastChangeReason(\"keyboard\");\n state.increment(largeStep);\n return;\n }\n\n if (key === \"PageDown\") {\n e.preventDefault();\n state._setLastChangeReason(\"keyboard\");\n state.decrement(largeStep);\n return;\n }\n\n if (key === \"Home\") {\n if (minValue !== undefined) {\n e.preventDefault();\n state._setLastChangeReason(\"keyboard\");\n state.decrementToMin();\n }\n return;\n }\n\n if (key === \"End\") {\n if (maxValue !== undefined) {\n e.preventDefault();\n state._setLastChangeReason(\"keyboard\");\n state.incrementToMax();\n }\n return;\n }\n\n if (key === \"Enter\") {\n state._setLastChangeReason(\"blur\");\n const committed = state.commit();\n onValueCommitted?.(committed, { reason: \"keyboard\" });\n return;\n }\n },\n [\n disabled,\n readOnly,\n state,\n largeStep,\n smallStep,\n minValue,\n maxValue,\n formatter,\n liveFormatter,\n parser,\n inputRef,\n allowDecimal,\n formatGroupedFraction,\n onValueCommitted,\n ]\n );\n\n // ── Blur handler ─────────────────────────────────────────────────────────\n const handleBlur = useCallback(\n (e: React.FocusEvent<HTMLInputElement>) => {\n state.setIsFocused(false);\n state._setLastChangeReason(\"blur\");\n const committed = state.commit();\n onValueCommitted?.(committed, { reason: \"blur\" });\n onBlur?.(e);\n },\n [state, onBlur, onValueCommitted]\n );\n\n // ── Focus handler ────────────────────────────────────────────────────────\n const handleFocus = useCallback(\n (e: React.FocusEvent<HTMLInputElement>) => {\n state.setIsFocused(true);\n onFocus?.(e);\n },\n [state, onFocus]\n );\n\n // ── Press-and-hold for increment/decrement buttons ───────────────────────\n const incrementHold = usePressAndHold(\n () => {\n state._setLastChangeReason(\"increment\");\n state.increment();\n },\n {\n delay: stepHoldDelay,\n interval: stepHoldInterval,\n disabled: disabled || !state.canIncrement,\n }\n );\n\n const decrementHold = usePressAndHold(\n () => {\n state._setLastChangeReason(\"decrement\");\n state.decrement();\n },\n {\n delay: stepHoldDelay,\n interval: stepHoldInterval,\n disabled: disabled || !state.canDecrement,\n }\n );\n\n // ── ARIA valuetext ───────────────────────────────────────────────────────\n const ariaValueText = useMemo(() => {\n if (state.numberValue == null) return undefined;\n return customFormatValue\n ? customFormatValue(state.numberValue)\n : formatter.format(state.numberValue);\n }, [state.numberValue, formatter, customFormatValue]);\n\n // ── RTL detection ────────────────────────────────────────────────────────\n const localeInfo = formatter.getLocaleInfo();\n\n // ── Out-of-range + validation detection (for aria-invalid + data-invalid) ─\n const isOutOfRange =\n state.numberValue !== null &&\n ((minValue !== undefined && state.numberValue < minValue) ||\n (maxValue !== undefined && state.numberValue > maxValue));\n\n const isInvalid = isOutOfRange || state.validationState === \"invalid\";\n\n // ── Prop maps ────────────────────────────────────────────────────────────\n\n // Track whether a label element is actually mounted. `labelProps.ref` (below)\n // registers/unregisters as it mounts, so `aria-labelledby` only points at the\n // label when it truly exists — for any render path (built-in component, custom\n // primitive, or fully headless), not just one that runs a specific effect.\n const labelCountRef = useRef(0);\n const [hasLabel, setHasLabel] = useState(false);\n const labelRef = useCallback<React.RefCallback<HTMLElement>>((node) => {\n if (node) {\n labelCountRef.current += 1;\n setHasLabel(true);\n } else if (labelCountRef.current > 0) {\n labelCountRef.current -= 1;\n if (labelCountRef.current === 0) setHasLabel(false);\n }\n }, []);\n\n // Fall back to the internal label id only when the consumer hasn't supplied\n // their own accessible name AND a label is actually rendered. Defaulting to\n // `labelId` otherwise points `aria-labelledby` at a `<label>` that may not\n // exist (e.g. when only `aria-label` is passed), producing a dangling ref.\n const ariaLabelledBy =\n props[\"aria-labelledby\"] ?? (props[\"aria-label\"] ? undefined : hasLabel ? labelId : undefined);\n\n const labelProps: NumberFieldAria[\"labelProps\"] = {\n id: labelId,\n htmlFor: inputId,\n ref: labelRef,\n };\n\n const groupProps: React.HTMLAttributes<HTMLDivElement> = {\n role: \"group\",\n \"aria-labelledby\": ariaLabelledBy,\n };\n\n const inputProps: React.InputHTMLAttributes<HTMLInputElement> = {\n id: inputId,\n type: \"text\",\n inputMode: \"decimal\",\n role: \"spinbutton\",\n autoComplete: \"off\",\n autoCorrect: \"off\",\n spellCheck: false,\n \"aria-label\": props[\"aria-label\"],\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": props[\"aria-describedby\"],\n \"aria-valuenow\": state.numberValue ?? undefined,\n \"aria-valuemin\": minValue,\n \"aria-valuemax\": maxValue,\n \"aria-valuetext\": ariaValueText,\n \"aria-disabled\": disabled || undefined,\n \"aria-readonly\": readOnly || undefined,\n \"aria-required\": required || undefined,\n \"aria-invalid\": isInvalid ? true : undefined,\n \"aria-errormessage\": isInvalid && state.validationError ? errorId : undefined,\n disabled,\n readOnly,\n required,\n value: state.inputValue,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n onBlur: handleBlur,\n onFocus: handleFocus,\n onPaste: handlePaste,\n onCopy: copyBehavior !== \"formatted\" ? handleCopy : undefined,\n onCut: copyBehavior !== \"formatted\" ? handleCut : undefined,\n onCompositionStart: handleCompositionStart,\n onCompositionEnd: handleCompositionEnd,\n // RTL: numbers are always LTR, align-right in RTL contexts\n // unicodeBidi: embed isolates the LTR number from surrounding RTL text\n style: localeInfo.isRTL\n ? { direction: \"ltr\", textAlign: \"right\", unicodeBidi: \"embed\" }\n : undefined,\n // Data attributes for CSS styling\n \"data-disabled\": disabled ? \"\" : undefined,\n \"data-readonly\": readOnly ? \"\" : undefined,\n \"data-required\": required ? \"\" : undefined,\n \"data-invalid\": isInvalid ? \"\" : undefined,\n \"data-rtl\": localeInfo.isRTL ? \"\" : undefined,\n } as React.InputHTMLAttributes<HTMLInputElement>;\n\n const hiddenInputProps: React.InputHTMLAttributes<HTMLInputElement> | null = name\n ? {\n type: \"hidden\",\n name,\n value: state.numberValue ?? \"\",\n \"aria-hidden\": true,\n }\n : null;\n\n const incrementButtonProps: React.ButtonHTMLAttributes<HTMLButtonElement> = {\n type: \"button\",\n tabIndex: -1,\n \"aria-label\": \"Increase\",\n disabled: disabled || !state.canIncrement,\n // Press-and-hold handlers replace simple onClick\n ...incrementHold,\n \"data-disabled\": disabled || !state.canIncrement ? \"\" : undefined,\n } as React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n const decrementButtonProps: React.ButtonHTMLAttributes<HTMLButtonElement> = {\n type: \"button\",\n tabIndex: -1,\n \"aria-label\": \"Decrease\",\n disabled: disabled || !state.canDecrement,\n // Press-and-hold handlers replace simple onClick\n ...decrementHold,\n \"data-disabled\": disabled || !state.canDecrement ? \"\" : undefined,\n } as React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n const descriptionProps: React.HTMLAttributes<HTMLElement> = {\n id: descriptionId,\n };\n\n const errorMessageProps: React.HTMLAttributes<HTMLElement> = {\n id: errorId,\n role: \"alert\",\n \"aria-live\": \"polite\",\n } as React.HTMLAttributes<HTMLElement>;\n\n return {\n labelProps,\n groupProps,\n inputProps,\n hiddenInputProps,\n incrementButtonProps,\n decrementButtonProps,\n descriptionProps,\n errorMessageProps,\n };\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { createFormatter } from \"../core/formatter.js\";\nimport type { UseNumberFieldStateOptions } from \"../core/types.js\";\n\ntype FormatOptions = Pick<\n UseNumberFieldStateOptions,\n | \"locale\"\n | \"formatOptions\"\n | \"prefix\"\n | \"suffix\"\n | \"minimumFractionDigits\"\n | \"maximumFractionDigits\"\n | \"fixedDecimalScale\"\n>;\n\n/**\n * Lightweight display-only formatting hook. Returns the formatted string for\n * a numeric value using the same Intl.NumberFormat engine as the full input.\n *\n * Use this when you need to display a formatted number in a read-only context\n * (table cells, summaries, labels) without the overhead of a full input state machine.\n *\n * @example\n * const price = useNumberFieldFormat(1234567.89, {\n * locale: 'en-US',\n * formatOptions: { style: 'currency', currency: 'USD' },\n * })\n * // price === \"$1,234,567.89\"\n *\n * @example\n * const pct = useNumberFieldFormat(0.4267, {\n * formatOptions: { style: 'percent', maximumFractionDigits: 1 },\n * })\n * // pct === \"42.7%\"\n */\nexport function useNumberFieldFormat(value: number | null, options: FormatOptions = {}): string {\n const {\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits,\n maximumFractionDigits,\n fixedDecimalScale,\n } = options;\n\n const formatter = useMemo(\n () =>\n createFormatter({\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits,\n maximumFractionDigits,\n fixedDecimalScale,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n locale,\n JSON.stringify(formatOptions),\n prefix,\n suffix,\n minimumFractionDigits,\n maximumFractionDigits,\n fixedDecimalScale,\n ]\n );\n\n return useMemo(() => {\n if (value === null || value === undefined) return \"\";\n return formatter.format(value);\n }, [value, formatter]);\n}\n","import { createContext, useContext } from \"react\";\nimport type { RefObject } from \"react\";\nimport type { NumberFieldAria, NumberFieldState, UseNumberFieldProps } from \"../core/types.js\";\n\nexport interface NumberFieldContextValue {\n state: NumberFieldState;\n aria: NumberFieldAria;\n inputRef: RefObject<HTMLInputElement | null>;\n props: UseNumberFieldProps;\n}\n\nexport const NumberFieldContext = createContext<NumberFieldContextValue | null>(null);\n\n/**\n * Hook for sub-components to access the NumberField context.\n * Throws if used outside NumberField.Root.\n */\nexport function useNumberFieldContext(): NumberFieldContextValue {\n const ctx = useContext(NumberFieldContext);\n if (!ctx) {\n throw new Error(\"[raqam] NumberField sub-components must be used inside <NumberField.Root>.\");\n }\n return ctx;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { NumberFieldState, ScrubAreaOptions } from \"../core/types.js\";\n\nexport interface ScrubAreaReturn {\n /** Whether pointer lock is currently active */\n isScrubbing: boolean;\n /** Props to spread on the scrub area element */\n scrubAreaProps: {\n role: string;\n tabIndex: number;\n style: React.CSSProperties;\n \"aria-label\": string;\n \"data-scrubbing\": string | undefined;\n onPointerDown: (e: React.PointerEvent) => void;\n onKeyDown: (e: React.KeyboardEvent) => void;\n };\n /**\n * Virtual cursor position (screen coordinates, updated by mousemove\n * during pointer lock). Use for positioning the ScrubAreaCursor.\n */\n virtualCursor: { x: number; y: number };\n}\n\n/**\n * Implements Pointer Lock API–based drag-to-scrub behavior.\n *\n * Flow:\n * 1. User presses pointer down → element requests pointer lock\n * 2. Browser hides cursor, starts delivering movementX/Y on mousemove\n * 3. Accumulated movement ÷ pixelSensitivity → increment/decrement calls\n * 4. Pointer lock exits on Escape key or programmatic exit\n */\nexport function useScrubArea(\n state: NumberFieldState,\n options: ScrubAreaOptions = {}\n): ScrubAreaReturn {\n const { direction = \"horizontal\", pixelSensitivity = 4 } = options;\n\n const [isScrubbing, setIsScrubbingLocal] = useState(false);\n\n // Keep stable refs to avoid stale closures in event listeners\n const stateRef = useRef(state);\n stateRef.current = state;\n\n const directionRef = useRef(direction);\n directionRef.current = direction;\n\n const sensitivityRef = useRef(pixelSensitivity);\n sensitivityRef.current = pixelSensitivity;\n\n const isScrubbingRef = useRef(false);\n const accumulatorRef = useRef(0);\n const elementRef = useRef<Element | null>(null);\n const virtualCursorRef = useRef({ x: 0, y: 0 });\n const [virtualCursor, setVirtualCursor] = useState({ x: 0, y: 0 });\n\n // Stable mousemove handler (always reads latest state via refs)\n const stableMouseMove = useRef((e: MouseEvent) => {\n if (!isScrubbingRef.current) return;\n\n // Update virtual cursor\n const nx = virtualCursorRef.current.x + e.movementX;\n const ny = virtualCursorRef.current.y + e.movementY;\n virtualCursorRef.current = { x: nx, y: ny };\n setVirtualCursor({ x: nx, y: ny });\n\n // Determine delta based on direction\n const dir = directionRef.current;\n let delta = 0;\n if (dir === \"horizontal\") {\n delta = e.movementX;\n } else if (dir === \"vertical\") {\n delta = -e.movementY;\n } else {\n delta = Math.abs(e.movementX) >= Math.abs(e.movementY) ? e.movementX : -e.movementY;\n }\n\n accumulatorRef.current += delta;\n\n // Fire step when accumulated movement exceeds sensitivity\n const sensitivity = sensitivityRef.current;\n while (accumulatorRef.current >= sensitivity) {\n stateRef.current.increment();\n accumulatorRef.current -= sensitivity;\n }\n while (accumulatorRef.current <= -sensitivity) {\n stateRef.current.decrement();\n accumulatorRef.current += sensitivity;\n }\n });\n\n // Stable pointer lock change handler\n const stablePointerLockChange = useRef(() => {\n if (document.pointerLockElement === elementRef.current) {\n // Lock acquired — start scrubbing\n isScrubbingRef.current = true;\n accumulatorRef.current = 0;\n setIsScrubbingLocal(true);\n stateRef.current.setIsScrubbing(true);\n document.addEventListener(\"mousemove\", stableMouseMove.current);\n } else {\n // Lock released — stop scrubbing\n isScrubbingRef.current = false;\n accumulatorRef.current = 0;\n document.removeEventListener(\"mousemove\", stableMouseMove.current);\n setIsScrubbingLocal(false);\n stateRef.current.setIsScrubbing(false);\n }\n });\n\n // Register stable pointerlockchange listener once on mount\n useEffect(() => {\n const handler = stablePointerLockChange.current;\n document.addEventListener(\"pointerlockchange\", handler);\n return () => {\n document.removeEventListener(\"pointerlockchange\", handler);\n document.removeEventListener(\"mousemove\", stableMouseMove.current);\n };\n }, []); // Empty deps — truly stable refs, no need to re-register\n\n const onPointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (stateRef.current.options.disabled || stateRef.current.options.readOnly) return;\n if (e.button !== 0) return;\n\n const el = e.currentTarget as HTMLElement;\n elementRef.current = el;\n virtualCursorRef.current = { x: e.clientX, y: e.clientY };\n setVirtualCursor({ x: e.clientX, y: e.clientY });\n\n el.requestPointerLock();\n },\n [] // No deps — reads via refs\n );\n\n // Keyboard support: arrow keys while scrub area is focused\n const onKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (stateRef.current.options.disabled || stateRef.current.options.readOnly) return;\n if (e.key === \"ArrowRight\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n stateRef.current.increment();\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowDown\") {\n e.preventDefault();\n stateRef.current.decrement();\n }\n }, []);\n\n // Cursor CSS based on direction\n const cursorStyle =\n direction === \"horizontal\" ? \"ew-resize\" : direction === \"vertical\" ? \"ns-resize\" : \"move\";\n\n const scrubAreaProps = {\n role: \"slider\",\n tabIndex: state.options.disabled ? -1 : 0,\n style: {\n cursor: state.options.disabled ? undefined : cursorStyle,\n userSelect: \"none\" as const,\n WebkitUserSelect: \"none\" as const,\n } satisfies React.CSSProperties,\n \"aria-label\": \"Scrub to change value\",\n \"data-scrubbing\": isScrubbing ? \"\" : undefined,\n onPointerDown,\n onKeyDown,\n };\n\n return { isScrubbing, scrubAreaProps, virtualCursor };\n}\n","\"use client\";\n\nimport React, { forwardRef, useMemo, useRef } from \"react\";\nimport type {\n NumberFieldRootProps,\n NumberFieldState,\n RenderProp,\n ScrubAreaCursorProps,\n ScrubAreaProps,\n} from \"../core/types.js\";\nimport { NumberFieldContext, useNumberFieldContext } from \"./context.js\";\nimport { useNumberField } from \"./useNumberField.js\";\nimport { useNumberFieldState } from \"./useNumberFieldState.js\";\nimport { useScrubArea } from \"./useScrubArea.js\";\n\n// ── Render prop utility ───────────────────────────────────────────────────────\n\n/**\n * Merge component props with a `render` prop.\n * Accepts either a React element or a render function.\n *\n * `forwardedRef` is threaded through explicitly because React 18 keeps `ref`\n * out of `element.props`, so a render-prop element would otherwise lose refs the\n * default element depends on — e.g. the label-registration ref carried by\n * `labelProps`. When provided, it takes precedence over the render element's own\n * `ref`; callers that need to keep a consumer ref must compose it into\n * `forwardedRef` themselves (see `<NumberField.Label>`), where it can be\n * memoized for a stable identity.\n */\nfunction renderWith(\n defaultElement: React.ReactElement,\n render: RenderProp | undefined,\n state: NumberFieldState,\n forwardedRef?: React.Ref<unknown>\n): React.ReactElement {\n if (!render) return defaultElement;\n\n const baseProps = { ...(defaultElement.props as Record<string, unknown>) };\n if (forwardedRef != null) baseProps.ref = forwardedRef;\n\n if (typeof render === \"function\") {\n return render(baseProps, state);\n }\n\n // Element form: clone with merged props.\n const merged = Object.assign({}, baseProps, render.props as Record<string, unknown>);\n if (forwardedRef != null) merged.ref = forwardedRef;\n return React.cloneElement(render, merged);\n}\n\n// ── Ref helpers ───────────────────────────────────────────────────────────────\n\n// React 19 exposes a React element's `ref` as a regular prop; React ≤18 stores\n// it on the element itself (and reading `element.ref` on React 19 logs a\n// deprecation warning), so branch on the version to read it without warnings.\nconst REF_IN_PROPS = Number.parseInt(React.version, 10) >= 19;\n\nfunction getElementRef(el: React.ReactElement): React.Ref<unknown> | undefined {\n if (REF_IN_PROPS) return (el.props as { ref?: React.Ref<unknown> }).ref;\n return (el as unknown as { ref?: React.Ref<unknown> }).ref;\n}\n\n/**\n * Compose multiple refs (callback or object) into one callback ref. Honors\n * React 19 cleanup-returning callback refs: each function ref's returned cleanup\n * (or a synthesized `ref(null)` for legacy refs / `current = null` for object\n * refs) is collected and run from the combined ref's own returned cleanup, so\n * consumer cleanups aren't dropped on unmount/ref change.\n */\nfunction mergeRefs<T>(...refs: (React.Ref<T> | undefined)[]): React.RefCallback<T> {\n return (node) => {\n const cleanups: (() => void)[] = [];\n for (const ref of refs) {\n if (ref == null) continue;\n if (typeof ref === \"function\") {\n const result = ref(node);\n cleanups.push(typeof result === \"function\" ? result : () => ref(null));\n } else {\n (ref as React.MutableRefObject<T | null>).current = node;\n cleanups.push(() => {\n (ref as React.MutableRefObject<T | null>).current = null;\n });\n }\n }\n return () => {\n for (const cleanup of cleanups) cleanup();\n };\n };\n}\n\n// ── Data attributes helper ────────────────────────────────────────────────────\n\nfunction stateDataAttrs(\n state: NumberFieldState,\n isInvalid: boolean\n): Record<string, string | undefined> {\n const { options } = state;\n return {\n \"data-disabled\": options.disabled ? \"\" : undefined,\n \"data-readonly\": options.readOnly ? \"\" : undefined,\n \"data-required\": options.required ? \"\" : undefined,\n \"data-scrubbing\": state.isScrubbing ? \"\" : undefined,\n \"data-focused\": state.isFocused ? \"\" : undefined,\n \"data-invalid\": isInvalid ? \"\" : undefined,\n };\n}\n\n// ── Root ──────────────────────────────────────────────────────────────────────\n\n// HTML attributes that belong on the wrapper div (not passed to state/aria hooks)\nconst DIV_ONLY_KEYS = new Set([\n \"className\",\n \"style\",\n \"id\",\n \"tabIndex\",\n \"title\",\n \"role\",\n \"aria-label\",\n \"data-testid\",\n \"onClick\",\n \"onMouseEnter\",\n \"onMouseLeave\",\n]);\n\nfunction splitProps(props: Record<string, unknown>) {\n const fieldProps: Record<string, unknown> = {};\n const divProps: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(props)) {\n if (DIV_ONLY_KEYS.has(key) || key.startsWith(\"data-\") || key.startsWith(\"aria-\")) {\n divProps[key] = val;\n } else {\n fieldProps[key] = val;\n }\n }\n return { fieldProps, divProps };\n}\n\nconst Root = forwardRef<HTMLDivElement, NumberFieldRootProps>(function NumberFieldRoot(\n { children, onValueChange, onValueCommitted, ...allProps },\n ref\n) {\n const inputRef = useRef<HTMLInputElement>(null);\n const { fieldProps, divProps } = splitProps(allProps as Record<string, unknown>);\n const props = fieldProps as Omit<\n NumberFieldRootProps,\n \"children\" | \"onValueChange\" | \"onValueCommitted\"\n >;\n\n // Keep a stable ref to onValueChange so the onChange closure never goes stale\n const onValueChangeRef = useRef(onValueChange);\n onValueChangeRef.current = onValueChange;\n\n // Keep a stable ref to the state object so onChange can read the current reason\n const stateRef = useRef<NumberFieldState | null>(null);\n\n // Wrap onChange to also fire onValueChange with the tracked reason.\n // This closure captures stateRef (stable) not state (changes each render).\n // _setLastChangeReason is called synchronously BEFORE the state mutation\n // that triggers onChange, so stateRef.current._getLastChangeReason() always\n // returns the correct reason at the time onChange fires.\n const wrappedProps = {\n ...props,\n // Forward onValueCommitted to the behavior hook, which fires it on blur/Enter.\n onValueCommitted,\n onChange: (value: number | null) => {\n props.onChange?.(value);\n if (onValueChangeRef.current && stateRef.current) {\n onValueChangeRef.current(value, {\n reason: stateRef.current._getLastChangeReason(),\n formattedValue: stateRef.current.inputValue,\n });\n }\n },\n };\n\n const state = useNumberFieldState(wrappedProps);\n stateRef.current = state; // always keep stateRef pointing to current state\n\n const aria = useNumberField(wrappedProps, state, inputRef);\n\n // Determine if field is invalid (out-of-range or failed validate)\n const isInvalid =\n state.validationState === \"invalid\" ||\n (state.numberValue !== null &&\n ((props.minValue !== undefined && state.numberValue < props.minValue) ||\n (props.maxValue !== undefined && state.numberValue > props.maxValue)));\n\n return (\n <NumberFieldContext.Provider value={{ state, aria, inputRef, props: wrappedProps }}>\n <div\n ref={ref}\n {...(divProps as React.HTMLAttributes<HTMLDivElement>)}\n {...stateDataAttrs(state, isInvalid)}\n >\n {children}\n </div>\n </NumberFieldContext.Provider>\n );\n});\n\n// ── Label ─────────────────────────────────────────────────────────────────────\n\ninterface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {\n render?: RenderProp;\n children?: React.ReactNode;\n}\n\nconst Label = forwardRef<HTMLLabelElement, LabelProps>(function NumberFieldLabel(\n { render, children, ...rest },\n ref\n) {\n const { aria, state } = useNumberFieldContext();\n // labelProps carries a registration ref; merge it with the forwarded ref and,\n // for the element render-prop form, the consumer's own ref on that element, so\n // all fire (the registration is what keeps Input/Group's aria-labelledby).\n // Memoized for a stable identity so React doesn't detach/reattach (and re-run\n // ref cleanups) every render — including across the hasLabel re-render.\n const { ref: labelRef, ...labelProps } = aria.labelProps;\n const renderRef = React.isValidElement(render) ? getElementRef(render) : undefined;\n const mergedRef = useMemo(() => mergeRefs(ref, labelRef, renderRef), [ref, labelRef, renderRef]);\n const el = (\n <label ref={mergedRef} {...labelProps} {...rest}>\n {children}\n </label>\n );\n return renderWith(el, render, state, mergedRef);\n});\n\n// ── Group ─────────────────────────────────────────────────────────────────────\n\ninterface GroupProps extends React.HTMLAttributes<HTMLDivElement> {\n render?: RenderProp;\n children?: React.ReactNode;\n}\n\nconst Group = forwardRef<HTMLDivElement, GroupProps>(function NumberFieldGroup(\n { render, children, ...rest },\n ref\n) {\n const { aria, state } = useNumberFieldContext();\n const el = (\n <div ref={ref} {...aria.groupProps} {...rest}>\n {children}\n </div>\n );\n return renderWith(el, render, state);\n});\n\n// ── Input ─────────────────────────────────────────────────────────────────────\n\ninterface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n render?: RenderProp;\n}\n\nconst Input = forwardRef<HTMLInputElement, InputProps>(function NumberFieldInput(\n { render, ...rest },\n _ref\n) {\n const { aria, state, inputRef } = useNumberFieldContext();\n const el = (\n <input ref={inputRef as React.RefObject<HTMLInputElement>} {...aria.inputProps} {...rest} />\n );\n return renderWith(el, render, state);\n});\n\n// ── Increment ─────────────────────────────────────────────────────────────────\n\ninterface IncrementProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n render?: RenderProp;\n children?: React.ReactNode;\n}\n\nconst Increment = forwardRef<HTMLButtonElement, IncrementProps>(function NumberFieldIncrement(\n { render, children, ...rest },\n ref\n) {\n const { aria, state } = useNumberFieldContext();\n const el = (\n <button ref={ref} {...aria.incrementButtonProps} {...rest}>\n {children ?? \"+\"}\n </button>\n );\n return renderWith(el, render, state);\n});\n\n// ── Decrement ─────────────────────────────────────────────────────────────────\n\ninterface DecrementProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n render?: RenderProp;\n children?: React.ReactNode;\n}\n\nconst Decrement = forwardRef<HTMLButtonElement, DecrementProps>(function NumberFieldDecrement(\n { render, children, ...rest },\n ref\n) {\n const { aria, state } = useNumberFieldContext();\n const el = (\n <button ref={ref} {...aria.decrementButtonProps} {...rest}>\n {children ?? \"−\"}\n </button>\n );\n return renderWith(el, render, state);\n});\n\n// ── HiddenInput ───────────────────────────────────────────────────────────────\n\nconst HiddenInput = function NumberFieldHiddenInput() {\n const { aria } = useNumberFieldContext();\n if (!aria.hiddenInputProps) return null;\n return <input {...aria.hiddenInputProps} />;\n};\n\n// ── ScrubArea ─────────────────────────────────────────────────────────────────\n\nconst ScrubArea = forwardRef<HTMLSpanElement, ScrubAreaProps>(function NumberFieldScrubArea(\n { render, children, direction = \"horizontal\", pixelSensitivity = 4, ...rest },\n ref\n) {\n const { state } = useNumberFieldContext();\n const { scrubAreaProps } = useScrubArea(state, { direction, pixelSensitivity });\n\n const el = (\n <span ref={ref} {...scrubAreaProps} {...(rest as React.HTMLAttributes<HTMLSpanElement>)}>\n {children}\n </span>\n );\n return renderWith(el, render, state);\n});\n\n// ── ScrubAreaCursor ───────────────────────────────────────────────────────────\n//\n// Renders a custom cursor element positioned at the virtual cursor location\n// during pointer lock. Use this to show a drag handle icon while scrubbing.\n// Rendered only when isScrubbing is true.\n\nconst ScrubAreaCursor = forwardRef<HTMLSpanElement, ScrubAreaCursorProps>(\n function NumberFieldScrubAreaCursor({ render, children, style, ...rest }, ref) {\n const { state } = useNumberFieldContext();\n\n if (!state.isScrubbing) return null;\n\n const el = (\n <span\n ref={ref}\n style={{\n position: \"fixed\",\n pointerEvents: \"none\",\n zIndex: 9999,\n ...style,\n }}\n {...(rest as React.HTMLAttributes<HTMLSpanElement>)}\n >\n {children}\n </span>\n );\n return renderWith(el, render, state);\n }\n);\n\n// ── Description ───────────────────────────────────────────────────────────────\n\ninterface DescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {\n children?: React.ReactNode;\n}\n\nconst Description = forwardRef<HTMLParagraphElement, DescriptionProps>(\n function NumberFieldDescription({ children, ...rest }, ref) {\n const { aria } = useNumberFieldContext();\n return (\n <p ref={ref} {...aria.descriptionProps} {...rest}>\n {children}\n </p>\n );\n }\n);\n\n// ── ErrorMessage ──────────────────────────────────────────────────────────────\n\ninterface ErrorMessageProps extends React.HTMLAttributes<HTMLParagraphElement> {\n children?: React.ReactNode;\n}\n\nconst ErrorMessage = forwardRef<HTMLParagraphElement, ErrorMessageProps>(\n function NumberFieldErrorMessage({ children, ...rest }, ref) {\n const { aria, state } = useNumberFieldContext();\n // If no children provided, fall back to the validation error string (if any)\n const content = children ?? state.validationError ?? null;\n if (!content) return null;\n return (\n <p ref={ref} {...aria.errorMessageProps} {...rest}>\n {content}\n </p>\n );\n }\n);\n\n// ── Formatted ─────────────────────────────────────────────────────────────────\n//\n// Read-only display of the current formatted value. Useful for showing the\n// formatted number inline without an editable input (e.g., in a data table).\n\ninterface FormattedProps extends React.HTMLAttributes<HTMLSpanElement> {\n render?: RenderProp;\n}\n\nconst Formatted = forwardRef<HTMLSpanElement, FormattedProps>(function NumberFieldFormatted(\n { render, ...rest },\n ref\n) {\n const { state } = useNumberFieldContext();\n const el = (\n <span ref={ref} aria-hidden=\"true\" {...rest}>\n {state.inputValue}\n </span>\n );\n return renderWith(el, render, state);\n});\n\n// ── Namespace export ──────────────────────────────────────────────────────────\n\nexport const NumberField = {\n Root,\n Label,\n Group,\n Input,\n Increment,\n Decrement,\n HiddenInput,\n ScrubArea,\n ScrubAreaCursor,\n Description,\n ErrorMessage,\n Formatted,\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/react/useControllableState.ts","../src/core/formatter.ts","../src/core/normalizer.ts","../src/core/parser.ts","../src/react/useNumberFieldState.ts","../src/core/cursor.ts","../src/react/usePressAndHold.ts","../src/react/useNumberField.ts","../src/react/useNumberFieldFormat.ts","../src/react/context.ts","../src/react/useScrubArea.ts","../src/react/NumberField.tsx"],"names":["useControllableState","value","defaultValue","onChange","isControlled","wasControlled","useRef","internalValue","setInternalValue","useState","set","useCallback","next","nextValue","formatterCache","getFormatter","locale","options","key","fmt","extractLocaleInfo","styledFmt","probeFmt","parts","decimalSeparator","groupingSeparator","minusSign","zero","part","rtlLocales","resolvedLocale","isRTL","createFormatter","opts","intlOptions","intlFmt","cachedLocaleInfo","getLocaleInfo","formatToParts","result","format","formatted","formatResult","p","BUILTIN_DIGIT_BLOCKS","registeredBlocks","normalizeDigits","input","ch","code","start","end","digit","localizeDigits","base","d","isIntermediateStripped","stripped","allowDecimal","createParser","allowNegative","isPercent","currencySymbol","stripAffordances","raw","info","s","accountingMatch","negative","parse","n","isIntermediate","clamp","min","max","v","preciseAdd","a","b","factor","decimalPlaces","eIdx","exp","dotIdx","fracLen","idx","useNumberFieldState","formatOptions","minValue","maxValue","step","largeStep","smallStep","maximumFractionDigits","minimumFractionDigits","fixedDecimalScale","clampBehavior","prefix","suffix","allowOutOfRange","validate","onRawChange","customFormatValue","effMinFrac","effMaxFrac","effFixedScale","formatter","useMemo","parser","numberValue","setNumberValue","lastEmittedRef","formatDisplay","initialDisplay","inputValue","setInputValueRaw","lastFormattedRef","rawValue","setRawValueState","runValidation","val","initialValidation","initVal","validationState","setValidationState","validationError","setValidationError","isScrubbing","setIsScrubbing","isFocused","setIsFocused","lastChangeReasonRef","_setLastChangeReason","reason","_getLastChangeReason","externalValue","prevExternalValueRef","ev","finite","formatKey","prevFormatKeyRef","applyValidation","vs","ve","setInputValue","knownValue","setNumericValue","rawStr","commit","clamped","committed","reparsed","safeNumberValue","resolvedLargeStep","resolvedSmallStep","canIncrement","canDecrement","increment","amount","decrement","incrementToMax","decrementToMin","isAccepted","countAcceptedBefore","str","cursor","normalised","count","i","getCaretBoundary","formattedValue","len","boundary","computeNewCursorPosition","oldInput","oldCursor","newFormatted","inputType","acceptedCount","before","minusBeforeCaret","newHasMinus","normNew","pos","snapToBoundary","usePressAndHold","callback","delay","interval","disabled","callbackRef","useEffect","delayRef","intervalRef","delayTimerRef","repeatTimerRef","isHeldRef","clearTimers","scheduleRepeat","currentInterval","nextInterval","onPointerDown","e","onPointerUp","onPointerLeave","escapeRegex","parseSpecialNotation","t","m","mult","useNumberField","props","state","inputRef","allowMouseWheel","rawLiveFormat","name","readOnly","required","onFocus","onBlur","copyBehavior","stepHoldDelay","stepHoldInterval","customParseValue","onValueCommitted","notation","liveFormat","autoId","useId","inputId","labelId","descriptionId","errorId","isPercentStyle","liveMaxFrac","liveFormatter","formatGroupedFraction","source","decIdx","fracMatch","pendingCursor","useLayoutEffect","el","handler","isComposing","handleCompositionStart","handleCompositionEnd","composedValue","normalized","displayValue","handleChange","rawInputValue","cursorPos","_m","offset","rt","handlePaste","text","li","special","sval","localeInfo","allowedCharsPattern","stripped2","result2","handleCopy","handleCut","handleKeyDown","decPos","selEnd","currentValue","rawEdited","parseResult","nextDisplay","isDigitChar","isAffordanceChar","direction","handleBlur","handleFocus","incrementHold","decrementHold","ariaValueText","isInvalid","labelCountRef","hasLabel","setHasLabel","labelRef","node","ariaLabelledBy","labelProps","groupProps","inputProps","hiddenInputProps","incrementButtonProps","decrementButtonProps","useNumberFieldFormat","NumberFieldContext","createContext","useNumberFieldContext","ctx","useContext","useScrubArea","pixelSensitivity","setIsScrubbingLocal","stateRef","directionRef","sensitivityRef","isScrubbingRef","accumulatorRef","elementRef","virtualCursorRef","virtualCursor","setVirtualCursor","stableMouseMove","nx","ny","dir","delta","sensitivity","stablePointerLockChange","onKeyDown","cursorStyle","scrubAreaProps","renderWith","defaultElement","render","forwardedRef","baseProps","merged","React","REF_IN_PROPS","SUPPORTS_REF_CLEANUP","getElementRef","mergeRefs","refs","attach","cleanups","ref","cleanup","stateDataAttrs","DIV_ONLY_KEYS","splitProps","fieldProps","divProps","Root","forwardRef","children","onValueChange","allProps","onValueChangeRef","wrappedProps","aria","jsx","Label","rest","renderRef","mergedRef","Group","Input","_ref","Increment","Decrement","HiddenInput","ScrubArea","ScrubAreaCursor","style","Description","ErrorMessage","content","Formatted","NumberField"],"mappings":"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","file":"react.js","sourcesContent":["import { useCallback, useRef, useState } from \"react\";\n\ninterface UseControllableStateOptions<T> {\n value?: T;\n defaultValue?: T;\n onChange?: (value: T) => void;\n}\n\n/**\n * Manages controlled vs uncontrolled state.\n * - If `value` is provided, the component is controlled.\n * - Otherwise it manages its own state starting from `defaultValue`.\n * Warns in dev mode if the component switches between controlled/uncontrolled.\n */\nexport function useControllableState<T>({\n value,\n defaultValue,\n onChange,\n}: UseControllableStateOptions<T>): [\n T | undefined,\n (next: T | ((prev: T | undefined) => T)) => void,\n] {\n const isControlled = value !== undefined;\n const wasControlled = useRef(isControlled);\n\n if (\n typeof window !== \"undefined\" &&\n (window as unknown as { __DEV__?: boolean }).__DEV__ !== false\n ) {\n if (wasControlled.current !== isControlled) {\n console.warn(\n `[raqam] Component is changing from ${\n wasControlled.current ? \"controlled\" : \"uncontrolled\"\n } to ${isControlled ? \"controlled\" : \"uncontrolled\"}. Decide between using a controlled or uncontrolled component and don't switch.`\n );\n }\n }\n\n const [internalValue, setInternalValue] = useState<T | undefined>(defaultValue);\n\n const set = useCallback(\n (next: T | ((prev: T | undefined) => T)) => {\n const nextValue =\n typeof next === \"function\"\n ? (next as (prev: T | undefined) => T)(isControlled ? value : internalValue)\n : next;\n\n if (!isControlled) {\n setInternalValue(nextValue);\n }\n onChange?.(nextValue);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [isControlled, value, internalValue, onChange]\n );\n\n return [isControlled ? value : internalValue, set];\n}\n","import type { FormatResult, LocaleInfo } from \"./types.js\";\n\n// ── Internal ──────────────────────────────────────────────────────────────────\n\n/** Probe value that will surface decimal AND grouping parts */\nconst PROBE_VALUE = 12345.6;\n\n/** Cache key = locale + JSON.stringify(options) */\nconst formatterCache = new Map<string, Intl.NumberFormat>();\n\nfunction getFormatter(\n locale: string | undefined,\n options: Intl.NumberFormatOptions | undefined\n): Intl.NumberFormat {\n const key = `${locale ?? \"\"}::${JSON.stringify(options ?? {})}`;\n let fmt = formatterCache.get(key);\n if (!fmt) {\n fmt = new Intl.NumberFormat(locale, options);\n formatterCache.set(key, fmt);\n }\n return fmt;\n}\n\n/** Extract locale meta from formatToParts — never hardcoded. */\nfunction extractLocaleInfo(\n locale: string | undefined,\n options: Intl.NumberFormatOptions | undefined\n): LocaleInfo {\n const styledFmt = getFormatter(locale, options);\n\n // Probe the separators with a NEUTRAL decimal formatter (same locale +\n // numbering system, but plain decimal style with a forced fraction). The\n // styled formatter can hide them — e.g. percent scales the probe so it has no\n // fraction (decimal separator invisible) and a positive value never yields a\n // minusSign. A negative, fractional decimal probe always surfaces all four.\n const probeFmt = getFormatter(locale, {\n minimumFractionDigits: 1,\n maximumFractionDigits: 1,\n numberingSystem: options?.numberingSystem,\n });\n const parts = probeFmt.formatToParts(-PROBE_VALUE);\n\n let decimalSeparator = \".\";\n let groupingSeparator = \",\";\n let minusSign = \"-\";\n let zero = \"0\";\n\n for (const part of parts) {\n if (part.type === \"decimal\") decimalSeparator = part.value;\n if (part.type === \"group\") groupingSeparator = part.value;\n if (part.type === \"minusSign\") minusSign = part.value;\n }\n\n // Detect locale zero digit\n for (const part of probeFmt.formatToParts(0)) {\n if (part.type === \"integer\") {\n zero = part.value;\n break;\n }\n }\n\n // RTL locales: Arabic / Hebrew / Persian / Urdu / Syriac etc.\n const rtlLocales = /^(ar|he|fa|ur|syc|nqo|ug|yi)/i;\n const resolvedLocale = styledFmt.resolvedOptions().locale;\n const isRTL = rtlLocales.test(resolvedLocale);\n\n return { decimalSeparator, groupingSeparator, minusSign, zero, isRTL };\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport interface FormatterOptions {\n locale?: string;\n formatOptions?: Intl.NumberFormatOptions;\n prefix?: string;\n suffix?: string;\n minimumFractionDigits?: number;\n maximumFractionDigits?: number;\n fixedDecimalScale?: boolean;\n}\n\nexport interface Formatter {\n format(value: number): string;\n formatToParts(value: number): Intl.NumberFormatPart[];\n getLocaleInfo(): LocaleInfo;\n formatResult(value: number): FormatResult;\n}\n\n/**\n * Create a formatter instance. Intl.NumberFormat is cached — safe to call\n * on every render.\n */\nexport function createFormatter(opts: FormatterOptions): Formatter {\n // Merge fraction digit overrides into formatOptions\n const intlOptions: Intl.NumberFormatOptions = { ...opts.formatOptions };\n\n if (opts.minimumFractionDigits !== undefined) {\n intlOptions.minimumFractionDigits = opts.minimumFractionDigits;\n }\n if (opts.maximumFractionDigits !== undefined) {\n intlOptions.maximumFractionDigits = opts.maximumFractionDigits;\n }\n if (opts.fixedDecimalScale && opts.maximumFractionDigits !== undefined) {\n intlOptions.minimumFractionDigits = opts.maximumFractionDigits;\n intlOptions.maximumFractionDigits = opts.maximumFractionDigits;\n }\n\n const intlFmt = getFormatter(opts.locale, intlOptions);\n // Lazy — computed once on first call\n let cachedLocaleInfo: LocaleInfo | null = null;\n\n function getLocaleInfo(): LocaleInfo {\n if (!cachedLocaleInfo) {\n cachedLocaleInfo = extractLocaleInfo(opts.locale, intlOptions);\n }\n return cachedLocaleInfo;\n }\n\n function formatToParts(value: number): Intl.NumberFormatPart[] {\n const parts = intlFmt.formatToParts(value);\n if (!opts.prefix && !opts.suffix) return parts;\n\n const result: Intl.NumberFormatPart[] = [];\n if (opts.prefix) result.push({ type: \"literal\", value: opts.prefix });\n result.push(...parts);\n if (opts.suffix) result.push({ type: \"literal\", value: opts.suffix });\n return result;\n }\n\n function format(value: number): string {\n if (!Number.isFinite(value)) return \"\";\n const formatted = intlFmt.format(value);\n return (opts.prefix ?? \"\") + formatted + (opts.suffix ?? \"\");\n }\n\n function formatResult(value: number): FormatResult {\n const parts = formatToParts(value);\n const formatted = parts.map((p) => p.value).join(\"\");\n return { formatted, parts };\n }\n\n return { format, formatToParts, getLocaleInfo, formatResult };\n}\n","import type { DigitBlock } from \"./types.js\";\n\n// ── Built-in digit blocks ────────────────────────────────────────────────────\n// These cover the digit systems required by the spec.\n// Additional blocks can be registered via registerLocale().\n\nconst BUILTIN_DIGIT_BLOCKS: DigitBlock[] = [\n [0x0660, 0x0669], // Arabic-Indic (arab)\n [0x06f0, 0x06f9], // Extended Arabic-Indic / Persian (arabext)\n [0x0966, 0x096f], // Devanagari / Hindi (deva)\n [0x09e6, 0x09ef], // Bengali (beng)\n [0x0e50, 0x0e59], // Thai (thai)\n];\n\n// Mutable registry — locale plugins can add blocks here\nconst registeredBlocks: DigitBlock[] = [...BUILTIN_DIGIT_BLOCKS];\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\nexport interface LocaleConfig {\n /** Extra digit block ranges to register */\n digitBlocks?: DigitBlock[];\n}\n\n/**\n * Register additional digit blocks (called by locale plugins as a side effect).\n * Duplicate ranges are silently ignored.\n */\nexport function registerLocale(config: LocaleConfig): void {\n if (!config.digitBlocks) return;\n for (const block of config.digitBlocks) {\n const already = registeredBlocks.some(([s]) => s === block[0]);\n if (!already) registeredBlocks.push(block);\n }\n}\n\n/**\n * Normalise any Unicode decimal digit in `input` to its ASCII equivalent (0–9).\n * Non-digit characters pass through unchanged.\n */\nexport function normalizeDigits(input: string): string {\n // Fast path: if there are no non-ASCII chars, return as-is\n if (!/[^\\u0020-\\u007e]/.test(input)) return input;\n\n return input.replace(/\\p{Nd}/gu, (ch) => {\n const code = ch.codePointAt(0)!;\n for (const [start, end] of registeredBlocks) {\n if (code >= start && code <= end) {\n return String(code - start);\n }\n }\n // Fallback: let JS try to parse it as a decimal digit\n const digit = Number.parseInt(ch, 10);\n return Number.isNaN(digit) ? ch : String(digit);\n });\n}\n\n/**\n * Inverse of {@link normalizeDigits}: map ASCII digits 0–9 to the locale's\n * native digit block (identified by its \"zero\" character). No-op when the\n * locale already uses ASCII digits. Used to keep intermediate (still-typing)\n * display strings in the user's native script.\n */\nexport function localizeDigits(input: string, zero: string): string {\n if (!zero || zero === \"0\") return input;\n const base = zero.codePointAt(0);\n if (base === undefined) return input;\n return input.replace(/[0-9]/g, (d) => String.fromCodePoint(base + (d.charCodeAt(0) - 48)));\n}\n\n/**\n * Returns true if the character is a non-Latin Unicode decimal digit\n * (i.e. would need normalization).\n */\nexport function isNonLatinDigit(ch: string): boolean {\n const code = ch.codePointAt(0);\n if (code === undefined) return false;\n if (code >= 0x30 && code <= 0x39) return false; // ASCII 0-9\n for (const [start, end] of registeredBlocks) {\n if (code >= start && code <= end) return true;\n }\n return false;\n}\n","import { createFormatter } from \"./formatter.js\";\nimport { normalizeDigits } from \"./normalizer.js\";\nimport type { LocaleInfo, ParseResult } from \"./types.js\";\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/**\n * Given an ASCII-normalised numeric string (`stripped` — digits, an optional\n * leading \"-\", and at most one \".\"), report whether it is a valid-but-incomplete\n * value that must NOT be reformatted while the user is still typing:\n * \"1.\" trailing decimal separator\n * \"1.0\" trailing zero after decimal\n * \"1.50\" trailing zeros after decimal\n * \".5\" leading decimal point (normalised to \"0.5\" only on blur)\n *\n * This runs on the *stripped* string, so grouping separators, prefixes,\n * suffixes and currency symbols never break the detection.\n */\nfunction isIntermediateStripped(stripped: string, allowDecimal: boolean): boolean {\n if (!allowDecimal) return false;\n if (/^-0+$/.test(stripped)) return true; // \"-0\" — user may still type \"-0.5\"\n if (/\\.$/.test(stripped)) return true; // \"1.\", \"-1.\"\n if (/\\.\\d*0$/.test(stripped)) return true; // \"1.0\", \"1.50\", \"1.230\"\n if (/^-?\\.\\d+$/.test(stripped)) return true; // \".5\", \"-.5\"\n return false;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport interface ParserOptions {\n locale?: string;\n formatOptions?: Intl.NumberFormatOptions;\n allowNegative?: boolean;\n allowDecimal?: boolean;\n prefix?: string;\n suffix?: string;\n}\n\nexport interface Parser {\n parse(input: string): ParseResult;\n isIntermediate(input: string): boolean;\n getLocaleInfo(): LocaleInfo;\n}\n\n/**\n * Create a locale-aware parser. Separator characters are extracted from\n * Intl.NumberFormat — never hardcoded.\n */\nexport function createParser(opts: ParserOptions = {}): Parser {\n const allowNegative = opts.allowNegative ?? true;\n const allowDecimal = opts.allowDecimal ?? true;\n // Percent fields hold the *fraction* (Intl multiplies by 100 on display), so\n // typed digits must be divided by 100: typing \"50\" means 50% i.e. value 0.5.\n const isPercent = opts.formatOptions?.style === \"percent\";\n\n // Re-use the formatter to get locale info\n const fmt = createFormatter({\n locale: opts.locale,\n formatOptions: opts.formatOptions,\n prefix: opts.prefix,\n suffix: opts.suffix,\n });\n\n // The literal currency symbol (e.g. \"$\", \"€\", or Arabic \"ج.م.\" which embeds\n // ASCII dots). Captured so it can be removed wholesale before separator\n // handling — otherwise its dots would be mistaken for a decimal point.\n let currencySymbol = \"\";\n if (opts.formatOptions?.style === \"currency\") {\n try {\n currencySymbol = fmt\n .formatToParts(1)\n .filter((p) => p.type === \"currency\")\n .map((p) => p.value)\n .join(\"\");\n } catch {\n currencySymbol = \"\";\n }\n }\n\n function getLocaleInfo(): LocaleInfo {\n return fmt.getLocaleInfo();\n }\n\n function stripAffordances(raw: string): string {\n const info = getLocaleInfo();\n\n // 1. Normalise non-Latin digits to ASCII\n let s = normalizeDigits(raw);\n\n // 1b. Remove the currency symbol wholesale (before separators are touched),\n // so a symbol containing ASCII dots — e.g. Arabic \"ج.م.\" — does not leave\n // stray \".\" that the numeric validation would reject.\n if (currencySymbol) {\n s = s.split(currencySymbol).join(\"\");\n }\n\n // 2. Accounting format: \"(1,234.56)\" or \"($1,234.56)\" → negative\n // Intl.NumberFormat with currencySign:\"accounting\" wraps negatives in parens\n const accountingMatch = s.match(/^\\((.+)\\)$/);\n if (accountingMatch) {\n s = `-${accountingMatch[1]}`;\n }\n\n // 3. Strip prefix / suffix\n if (opts.prefix && s.startsWith(opts.prefix)) {\n s = s.slice(opts.prefix.length);\n }\n if (opts.suffix && s.endsWith(opts.suffix)) {\n s = s.slice(0, -opts.suffix.length);\n }\n\n // 4. Strip grouping separators (escape special chars)\n if (info.groupingSeparator) {\n s = s.split(info.groupingSeparator).join(\"\");\n }\n\n // 5. Replace locale decimal separator with ASCII \".\"\n if (info.decimalSeparator !== \".\") {\n s = s.split(info.decimalSeparator).join(\".\");\n }\n\n // 6. Replace locale minus sign with ASCII \"-\"\n if (info.minusSign !== \"-\") {\n s = s.split(info.minusSign).join(\"-\");\n }\n // Also normalise the Unicode minus U+2212 (used by fa/sv/fi/nb… and often\n // pasted) so it is never stripped as a non-numeric character below.\n if (s.includes(\"−\")) {\n s = s.split(\"−\").join(\"-\");\n }\n\n // 7. Strip currency symbol, percent sign, spaces that Intl might prepend/append\n // Strip any remaining non-numeric chars except digits, \".\", \"-\"\n // (handles currency prefixes/suffixes from Intl)\n s = s.replace(/[^\\d.\\-]/g, \"\").trim();\n\n // 8. Collapse minus signs to a single leading one, so stray minuses typed in\n // the middle (\"1-23\") or doubled (\"--5\") never invalidate the whole value.\n if (s.includes(\"-\")) {\n const negative = s.startsWith(\"-\");\n s = s.replace(/-/g, \"\");\n if (negative) s = `-${s}`;\n }\n\n return s;\n }\n\n function parse(input: string): ParseResult {\n if (!input || input.trim() === \"\") {\n return { value: null, isValid: false, isIntermediate: false };\n }\n\n // Strip *first*, so intermediate detection never trips over grouping\n // separators, prefixes, suffixes or currency symbols.\n const stripped = stripAffordances(input);\n\n if (stripped === \"\") {\n return { value: null, isValid: false, isIntermediate: false };\n }\n\n // Lone minus — intermediate only if negatives are allowed.\n if (stripped === \"-\") {\n return { value: null, isValid: false, isIntermediate: allowNegative };\n }\n\n // Lone decimal point (\".\" or \"-.\") — intermediate only if decimals allowed.\n if (stripped === \".\" || stripped === \"-.\") {\n return {\n value: null,\n isValid: false,\n isIntermediate: allowDecimal && (stripped === \".\" || allowNegative),\n };\n }\n\n if (!allowNegative && stripped.startsWith(\"-\")) {\n return { value: null, isValid: false, isIntermediate: false };\n }\n\n if (!allowDecimal && stripped.includes(\".\")) {\n return { value: null, isValid: false, isIntermediate: false };\n }\n\n // Accept integers and decimals with the dot either trailing (\"1.\") or\n // leading (\".5\") so partially-typed values still yield a numeric value.\n if (!/^-?(?:\\d+\\.?\\d*|\\.\\d+)$/.test(stripped)) {\n return { value: null, isValid: false, isIntermediate: false };\n }\n\n let n = Number.parseFloat(stripped);\n if (!Number.isFinite(n)) {\n return { value: null, isValid: false, isIntermediate: false };\n }\n // Normalise negative zero so consumers never receive -0 from onChange.\n if (Object.is(n, -0)) n = 0;\n // Percent: divide by 100, snapping to canonical precision so the IEEE-754\n // division artifact (12.99/100 = 0.12990000000000002) never surfaces.\n if (isPercent && n !== 0) n = Number((n / 100).toPrecision(15));\n\n // A trailing-zero / trailing-dot / leading-dot value is still a real number\n // (so it is never wiped on blur) but must not be reformatted mid-typing.\n return {\n value: n,\n isValid: true,\n isIntermediate: isIntermediateStripped(stripped, allowDecimal),\n };\n }\n\n function isIntermediate(input: string): boolean {\n return parse(input).isIntermediate;\n }\n\n return { parse, isIntermediate, getLocaleInfo };\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\";\nimport { createFormatter } from \"../core/formatter.js\";\nimport { createParser } from \"../core/parser.js\";\nimport type { ChangeReason, NumberFieldState, UseNumberFieldStateOptions } from \"../core/types.js\";\nimport { useControllableState } from \"./useControllableState.js\";\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction clamp(value: number, min?: number, max?: number): number {\n let v = value;\n if (min !== undefined) v = Math.max(v, min);\n if (max !== undefined) v = Math.min(v, max);\n return v;\n}\n\nfunction preciseAdd(a: number, b: number): number {\n // Simple float precision fix — avoids 0.1 + 0.2 = 0.30000000000000004\n const precision = Math.max(decimalPlaces(a), decimalPlaces(b));\n const factor = 10 ** precision;\n return Math.round(a * factor + b * factor) / factor;\n}\n\nfunction decimalPlaces(n: number): number {\n if (!Number.isFinite(n)) return 0;\n const s = String(n);\n // Exponential form (e.g. \"1e-7\", \"1.5e-7\") — String() uses it below 1e-6.\n const eIdx = s.indexOf(\"e\");\n if (eIdx !== -1) {\n const exp = Number(s.slice(eIdx + 1));\n const dotIdx = s.indexOf(\".\");\n const fracLen = dotIdx === -1 ? 0 : eIdx - dotIdx - 1;\n return Math.max(0, fracLen - exp);\n }\n const idx = s.indexOf(\".\");\n return idx === -1 ? 0 : s.length - idx - 1;\n}\n\n// ── Hook ──────────────────────────────────────────────────────────────────────\n\nexport function useNumberFieldState(options: UseNumberFieldStateOptions): NumberFieldState {\n const {\n locale,\n formatOptions,\n minValue,\n maxValue,\n step = 1,\n largeStep,\n smallStep,\n allowNegative = true,\n allowDecimal = true,\n maximumFractionDigits,\n minimumFractionDigits,\n fixedDecimalScale,\n clampBehavior = \"blur\",\n prefix,\n suffix,\n allowOutOfRange = false,\n validate,\n onRawChange,\n formatValue: customFormatValue,\n } = options;\n\n // When decimals are disallowed, force the formatter to 0 fraction digits so\n // currency / fixedDecimalScale never pad \".00\" (which the dot-strip would then\n // re-read, exploding the value). See XF-2.\n const effMinFrac = allowDecimal ? minimumFractionDigits : 0;\n const effMaxFrac = allowDecimal ? maximumFractionDigits : 0;\n const effFixedScale = allowDecimal ? fixedDecimalScale : false;\n\n // ── Formatter & parser (re-created only when deps change) ──────────────────\n const formatter = useMemo(\n () =>\n createFormatter({\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits: effMinFrac,\n maximumFractionDigits: effMaxFrac,\n fixedDecimalScale: effFixedScale,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n locale,\n // JSON-serialize to detect object identity changes\n JSON.stringify(formatOptions),\n prefix,\n suffix,\n effMinFrac,\n effMaxFrac,\n effFixedScale,\n ]\n );\n\n const parser = useMemo(\n () =>\n createParser({\n locale,\n formatOptions,\n allowNegative,\n allowDecimal,\n prefix,\n suffix,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [locale, JSON.stringify(formatOptions), allowNegative, allowDecimal, prefix, suffix]\n );\n\n // ── Controlled/uncontrolled numeric value ──────────────────────────────────\n const [numberValue, setNumberValue] = useControllableState<number | null>({\n value: options.value,\n defaultValue: options.defaultValue ?? null,\n onChange: options.onChange,\n });\n\n // Last numeric value we emitted ourselves — used to tell our own onChange echo\n // apart from a genuine external controlled-value change (see sync block below).\n const lastEmittedRef = useRef<number | null | undefined>(\n options.value ?? options.defaultValue ?? null\n );\n\n // ── Display string ─────────────────────────────────────────────────────────\n // Stored in local state — can transiently diverge from numberValue\n // (e.g. while typing \"1.\" which isn't a valid JS number yet)\n const formatDisplay = useCallback(\n (n: number): string =>\n // Normalise -0 so it never renders as \"-0\" on any path (mount included).\n customFormatValue\n ? customFormatValue(Object.is(n, -0) ? 0 : n)\n : formatter.format(Object.is(n, -0) ? 0 : n),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [formatter, customFormatValue]\n );\n\n const initialDisplay = useMemo(() => {\n if (options.defaultValue != null) {\n return formatDisplay(options.defaultValue);\n }\n if (options.value != null) {\n return formatDisplay(options.value);\n }\n return \"\";\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []); // Only on mount\n\n const [inputValue, setInputValueRaw] = useState<string>(initialDisplay);\n\n // Track last formatted value so we can sync controlled value changes\n const lastFormattedRef = useRef<string>(initialDisplay);\n\n // ── Raw value (precision-preserving string) ────────────────────────────────\n const [rawValue, setRawValueState] = useState<string | null>(\n options.defaultValue != null ? String(options.defaultValue) : null\n );\n\n // ── Validation state ───────────────────────────────────────────────────────\n const runValidation = useCallback(\n (\n val: number | null\n ): { validationState: \"valid\" | \"invalid\"; validationError: string | null } => {\n if (!validate) return { validationState: \"valid\", validationError: null };\n const result = validate(val);\n if (result === false) return { validationState: \"invalid\", validationError: null };\n if (typeof result === \"string\")\n return { validationState: \"invalid\", validationError: result };\n return { validationState: \"valid\", validationError: null };\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [validate]\n );\n\n const initialValidation = useMemo(() => {\n const initVal = options.defaultValue ?? options.value ?? null;\n return runValidation(initVal != null ? initVal : null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []); // Only on mount\n\n const [validationState, setValidationState] = useState<\"valid\" | \"invalid\">(\n initialValidation.validationState\n );\n const [validationError, setValidationError] = useState<string | null>(\n initialValidation.validationError\n );\n\n // ── isScrubbing / isFocused state ──────────────────────────────────────────\n const [isScrubbing, setIsScrubbing] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n // ── Change reason ref (no re-render needed) ────────────────────────────────\n const lastChangeReasonRef = useRef<ChangeReason>(\"input\");\n const _setLastChangeReason = useCallback((reason: ChangeReason) => {\n lastChangeReasonRef.current = reason;\n }, []);\n\n const _getLastChangeReason = useCallback((): ChangeReason => {\n return lastChangeReasonRef.current;\n }, []);\n\n // ── Sync controlled value → display string when value changes externally ───\n // We must distinguish a *genuine* external change (parent set a new value,\n // form reset/prefill, etc.) from the echo of our own onChange. `lastEmittedRef`\n // tracks the value we last emitted; if the incoming controlled value differs\n // from it, the change came from outside and the display must be re-synced.\n const externalValue = options.value;\n const prevExternalValueRef = useRef(externalValue);\n // Object.is (not !==) so a controlled value of NaN compares equal to itself\n // and never triggers an unconditional render-phase setState → infinite loop.\n if (!Object.is(prevExternalValueRef.current, externalValue)) {\n prevExternalValueRef.current = externalValue;\n if (!Object.is(externalValue, lastEmittedRef.current)) {\n lastEmittedRef.current = externalValue;\n // Normalise -0 so a controlled value of -0 displays as \"0\", matching the\n // typed and commit paths.\n const ev = Object.is(externalValue, -0) ? 0 : externalValue;\n const finite = ev != null && Number.isFinite(ev);\n const formatted = finite ? formatDisplay(ev as number) : \"\";\n lastFormattedRef.current = formatted;\n setInputValueRaw(formatted);\n setRawValueState(finite ? String(ev) : null);\n }\n }\n\n // ── Reformat the display when locale / formatOptions change at runtime ──────\n // When the field is not being actively edited, a locale or format change must\n // re-render the existing value in the new format (e.g. switching en-US → de-DE).\n const formatKey = `${locale ?? \"\"}|${JSON.stringify(formatOptions ?? {})}|${prefix ?? \"\"}|${suffix ?? \"\"}|${effMinFrac ?? \"\"}|${effMaxFrac ?? \"\"}|${effFixedScale ?? \"\"}`;\n const prevFormatKeyRef = useRef(formatKey);\n if (prevFormatKeyRef.current !== formatKey) {\n prevFormatKeyRef.current = formatKey;\n if (numberValue != null && Number.isFinite(numberValue) && !isFocused) {\n const formatted = formatDisplay(numberValue);\n if (formatted !== inputValue) {\n setInputValueRaw(formatted);\n lastFormattedRef.current = formatted;\n }\n }\n }\n\n // ── Internal helper: apply validation after a value change ────────────────\n const applyValidation = useCallback(\n (val: number | null) => {\n const { validationState: vs, validationError: ve } = runValidation(val);\n setValidationState(vs);\n setValidationError(ve);\n },\n [runValidation]\n );\n\n // ── setInputValue ──────────────────────────────────────────────────────────\n // `knownValue` lets the caller supply the exact numeric value when `val` is a\n // formatted string the parser cannot faithfully reverse (compact \"2.5K\",\n // scientific, unit). Without it, the value is derived by parsing `val`.\n const setInputValue = useCallback(\n (val: string, knownValue?: number | null) => {\n const value = knownValue !== undefined ? knownValue : parser.parse(val).value;\n\n // Strict clamping: reject input that goes out of range (skipped when allowOutOfRange)\n if (clampBehavior === \"strict\" && !allowOutOfRange && value !== null) {\n if (minValue !== undefined && value < minValue) return;\n if (maxValue !== undefined && value > maxValue) return;\n }\n\n setInputValueRaw(val);\n lastEmittedRef.current = value;\n setNumberValue(value);\n // rawValue tracks what user typed, not the formatted output\n setRawValueState(value !== null ? val : null);\n onRawChange?.(value !== null ? val : null);\n applyValidation(value);\n },\n [\n parser,\n clampBehavior,\n allowOutOfRange,\n minValue,\n maxValue,\n setNumberValue,\n onRawChange,\n applyValidation,\n ]\n );\n\n // ── setNumberValue (external) ──────────────────────────────────────────────\n const setNumericValue = useCallback(\n (val: number | null) => {\n lastEmittedRef.current = val;\n setNumberValue(val);\n if (val != null) {\n const formatted = formatDisplay(val);\n setInputValueRaw(formatted);\n lastFormattedRef.current = formatted;\n const rawStr = String(val);\n setRawValueState(rawStr);\n onRawChange?.(rawStr);\n } else {\n setInputValueRaw(\"\");\n lastFormattedRef.current = \"\";\n setRawValueState(null);\n onRawChange?.(null);\n }\n applyValidation(val);\n },\n [formatDisplay, setNumberValue, onRawChange, applyValidation]\n );\n\n // ── commit (called on blur) ────────────────────────────────────────────────\n const commit = useCallback((): number | null => {\n if (numberValue == null) {\n setInputValueRaw(\"\");\n lastFormattedRef.current = \"\";\n return null;\n }\n\n let clamped = numberValue;\n // Clamp on blur, unless allowOutOfRange is true\n if (clampBehavior === \"blur\" && !allowOutOfRange) {\n clamped = clamp(numberValue, minValue, maxValue);\n }\n // Normalise negative zero so \"-0\" commits as plain \"0\"\n if (Object.is(clamped, -0)) clamped = 0;\n\n const formatted = formatDisplay(clamped);\n setInputValueRaw(formatted);\n lastFormattedRef.current = formatted;\n\n // Round the committed value to the displayed precision so the numeric value\n // never diverges from what is shown (e.g. a percent field that rounds the\n // live-typed fraction down to its configured scale on blur). Only adopt the\n // reparsed value when it round-trips exactly back to `formatted` — this skips\n // non-invertible notations (compact \"2.5K\", scientific, unit) and any custom\n // formatter whose output the parser cannot faithfully reverse.\n let committed = clamped;\n if (!customFormatValue) {\n const reparsed = parser.parse(formatted).value;\n if (reparsed !== null && Number.isFinite(reparsed) && formatDisplay(reparsed) === formatted) {\n committed = reparsed;\n }\n }\n\n if (committed !== numberValue) {\n lastEmittedRef.current = committed;\n setNumberValue(committed);\n }\n applyValidation(committed);\n return committed;\n }, [\n numberValue,\n clampBehavior,\n allowOutOfRange,\n minValue,\n maxValue,\n parser,\n formatDisplay,\n customFormatValue,\n setNumberValue,\n applyValidation,\n ]);\n\n // Treat a non-finite value (NaN/Infinity from a bad default/controlled value)\n // as empty so it never reaches ARIA, the hidden form input, or arithmetic.\n const safeNumberValue = numberValue != null && Number.isFinite(numberValue) ? numberValue : null;\n\n // ── Step computation ───────────────────────────────────────────────────────\n const resolvedLargeStep = largeStep ?? step * 10;\n const resolvedSmallStep = smallStep ?? step * 0.1;\n\n const canIncrement =\n !options.disabled &&\n !options.readOnly &&\n (allowOutOfRange ||\n maxValue === undefined ||\n (safeNumberValue ?? Number.NEGATIVE_INFINITY) < maxValue);\n\n const canDecrement =\n !options.disabled &&\n !options.readOnly &&\n (allowOutOfRange ||\n minValue === undefined ||\n (safeNumberValue ?? Number.POSITIVE_INFINITY) > minValue);\n\n const increment = useCallback(\n (amount?: number) => {\n const s = amount ?? step;\n const base = safeNumberValue ?? 0;\n const raw = preciseAdd(base, s);\n const next = allowOutOfRange ? raw : clamp(raw, minValue, maxValue);\n setNumericValue(next);\n },\n [safeNumberValue, step, minValue, maxValue, allowOutOfRange, setNumericValue]\n );\n\n const decrement = useCallback(\n (amount?: number) => {\n const s = amount ?? step;\n const base = safeNumberValue ?? 0;\n const raw = preciseAdd(base, -s);\n const next = allowOutOfRange ? raw : clamp(raw, minValue, maxValue);\n setNumericValue(next);\n },\n [safeNumberValue, step, minValue, maxValue, allowOutOfRange, setNumericValue]\n );\n\n const incrementToMax = useCallback(() => {\n if (maxValue !== undefined) setNumericValue(maxValue);\n }, [maxValue, setNumericValue]);\n\n const decrementToMin = useCallback(() => {\n if (minValue !== undefined) setNumericValue(minValue);\n }, [minValue, setNumericValue]);\n\n return {\n inputValue,\n numberValue: safeNumberValue,\n rawValue,\n canIncrement,\n canDecrement,\n isScrubbing,\n setIsScrubbing,\n isFocused,\n setIsFocused,\n validationState,\n validationError,\n _setLastChangeReason,\n _getLastChangeReason,\n setInputValue,\n setNumberValue: setNumericValue,\n commit,\n increment,\n decrement,\n incrementToMax,\n decrementToMin,\n options: {\n ...options,\n step,\n largeStep: resolvedLargeStep,\n smallStep: resolvedSmallStep,\n },\n };\n}\n","import { normalizeDigits } from \"./normalizer.js\";\nimport type { CaretBoundary, LocaleInfo } from \"./types.js\";\n\n// ── Accepted-character helpers ────────────────────────────────────────────────\n\n/**\n * Returns true if `ch` is an \"accepted\" character — one that the user typed\n * intentionally and that contributes to the numeric value:\n * - ASCII digit 0-9\n * - The locale decimal separator\n * - The locale minus sign\n */\nfunction isAccepted(ch: string, info: LocaleInfo): boolean {\n if (ch >= \"0\" && ch <= \"9\") return true;\n if (ch === info.decimalSeparator) return true;\n if (ch === info.minusSign || ch === \"-\") return true;\n // ASCII \".\" stands in for the decimal point in locales whose separator is\n // non-ASCII (ar/fa: ٫) — but not when \".\" is the grouping separator (de-DE).\n if (ch === \".\" && info.decimalSeparator !== \".\" && info.groupingSeparator !== \".\") return true;\n return false;\n}\n\n/**\n * Count how many \"accepted\" characters appear before position `cursor`\n * in `str` (after normalising non-Latin digits to ASCII).\n */\nfunction countAcceptedBefore(str: string, cursor: number, info: LocaleInfo): number {\n const normalised = normalizeDigits(str);\n let count = 0;\n for (let i = 0; i < cursor && i < normalised.length; i++) {\n if (isAccepted(normalised[i]!, info)) count++;\n }\n return count;\n}\n\n// ── Caret boundary ────────────────────────────────────────────────────────────\n\n/**\n * Build a boolean array of length `formattedValue.length + 1`.\n * `true` → cursor may rest at this position.\n * `false` → cursor must snap away (sits inside a formatting-only character\n * such as a grouping separator or a currency prefix).\n *\n * Rules:\n * - Start and end positions are always valid.\n * - A position immediately AFTER a grouping separator is invalid (the\n * cursor would look like it's between two digits but moving left would\n * skip the comma).\n * - A position immediately BEFORE a grouping separator is valid.\n */\nexport function getCaretBoundary(formattedValue: string, info: LocaleInfo): CaretBoundary {\n const len = formattedValue.length;\n const boundary: CaretBoundary = new Array(len + 1).fill(true) as boolean[];\n\n for (let i = 0; i < len; i++) {\n const ch = formattedValue[i]!;\n if (ch === info.groupingSeparator) {\n // Position immediately after the grouping separator is invalid\n boundary[i + 1] = false;\n }\n }\n\n // First and last are always valid\n boundary[0] = true;\n boundary[len] = true;\n\n return boundary;\n}\n\n// ── Cursor computation ────────────────────────────────────────────────────────\n\n/**\n * Compute the new cursor position in `newFormatted` that corresponds\n * semantically to `oldCursor` in `oldInput`.\n *\n * Algorithm (3 stages from the spec):\n *\n * 1. Count accepted characters before `oldCursor` in `oldInput`.\n * 2. Adjust for backspace-over-separator edge case.\n * 3. Walk `newFormatted` to find the position where the same count of\n * accepted chars precede it; snap to the nearest valid boundary.\n *\n * @param oldInput The raw string the user just typed into (pre-format)\n * @param oldCursor selectionStart captured from the native event\n * @param newFormatted The formatted string we're about to display\n * @param info Locale separators\n * @param inputType e.nativeEvent.inputType (optional — for backspace detection)\n */\nexport function computeNewCursorPosition(\n oldInput: string,\n oldCursor: number,\n newFormatted: string,\n info: LocaleInfo,\n inputType?: string\n): number {\n const normalised = normalizeDigits(oldInput);\n\n // Stage 1: count accepted chars before cursor in old input\n let acceptedCount = countAcceptedBefore(normalised, oldCursor, info);\n\n // Stage 1b: accounting/parens negatives drop the minus sign. If a minus was\n // counted before the caret but the reformatted output represents the sign\n // without one (e.g. \"($1.00)\"), the accepted-char counts are off by one —\n // correct for it so integer digits don't land inside the fraction.\n const before = oldInput.slice(0, oldCursor);\n const minusBeforeCaret = before.includes(\"-\") || before.includes(info.minusSign);\n const newHasMinus = newFormatted.includes(\"-\") || newFormatted.includes(info.minusSign);\n if (minusBeforeCaret && !newHasMinus) {\n acceptedCount = Math.max(0, acceptedCount - 1);\n }\n\n // Stage 2: backspace on grouping separator — also delete the preceding digit\n if (\n inputType === \"deleteContentBackward\" &&\n oldCursor > 0 &&\n oldInput[oldCursor - 1] === info.groupingSeparator\n ) {\n // The separator was deleted but we want to remove the preceding digit too\n acceptedCount = Math.max(0, acceptedCount - 1);\n }\n\n // Stage 3: build boundary and walk new formatted string\n const boundary = getCaretBoundary(newFormatted, info);\n const normNew = normalizeDigits(newFormatted);\n let count = 0;\n let pos = 0;\n\n for (let i = 0; i < normNew.length; i++) {\n if (count === acceptedCount) {\n pos = i;\n break;\n }\n if (isAccepted(normNew[i]!, info)) count++;\n pos = i + 1;\n }\n\n // If we ran through the entire string without reaching the target count,\n // place the cursor at the end. Note: acceptedCount === 0 means we correctly\n // want pos = 0 (set in the loop), so we must NOT override that case.\n if (acceptedCount > 0 && count < acceptedCount) {\n pos = newFormatted.length;\n }\n\n // Snap to nearest valid boundary\n pos = snapToBoundary(pos, boundary);\n\n return pos;\n}\n\n/**\n * If `pos` is at a false (invalid) boundary position, find the nearest\n * true position. Prefers moving forward; falls back to backward.\n */\nfunction snapToBoundary(pos: number, boundary: CaretBoundary): number {\n if (boundary[pos]) return pos;\n\n // Try forward first\n for (let i = pos + 1; i < boundary.length; i++) {\n if (boundary[i]) return i;\n }\n // Fall back to backward\n for (let i = pos - 1; i >= 0; i--) {\n if (boundary[i]) return i;\n }\n return 0;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef } from \"react\";\n\nexport interface UsePressAndHoldOptions {\n /** Milliseconds before repeating starts (default: 400) */\n delay?: number;\n /** Initial milliseconds between repeats — halves each tick, floors at 50 (default: 200) */\n interval?: number;\n /** Whether the element is disabled */\n disabled?: boolean;\n}\n\nexport interface PressAndHoldProps {\n onPointerDown: (e: React.PointerEvent) => void;\n onPointerUp: (e: React.PointerEvent) => void;\n onPointerLeave: (e: React.PointerEvent) => void;\n}\n\n/**\n * Returns pointer event handlers that call `callback` immediately on press,\n * then repeatedly with accelerating frequency while held down.\n *\n * Acceleration schedule (default settings):\n * immediate → 400ms wait → 200ms → 100ms → 50ms (floor, stays until release)\n *\n * All timing is handled via refs — zero state updates, zero re-renders.\n */\nexport function usePressAndHold(\n callback: () => void,\n options: UsePressAndHoldOptions = {}\n): PressAndHoldProps {\n const { delay = 400, interval = 200, disabled = false } = options;\n\n // Stable refs so handlers don't re-create on every render\n const callbackRef = useRef(callback);\n useEffect(() => {\n callbackRef.current = callback;\n });\n\n const delayRef = useRef(delay);\n useEffect(() => {\n delayRef.current = delay;\n });\n\n const intervalRef = useRef(interval);\n useEffect(() => {\n intervalRef.current = interval;\n });\n\n // Timer handle refs (null = no active timer)\n const delayTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const repeatTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const isHeldRef = useRef(false);\n\n const clearTimers = useCallback(() => {\n isHeldRef.current = false;\n if (delayTimerRef.current !== null) {\n clearTimeout(delayTimerRef.current);\n delayTimerRef.current = null;\n }\n if (repeatTimerRef.current !== null) {\n clearTimeout(repeatTimerRef.current);\n repeatTimerRef.current = null;\n }\n }, []);\n\n // Recursive accelerating repeat\n const scheduleRepeat = useCallback((currentInterval: number) => {\n if (!isHeldRef.current) return;\n callbackRef.current();\n const nextInterval = Math.max(50, Math.floor(currentInterval / 2));\n repeatTimerRef.current = setTimeout(() => {\n scheduleRepeat(nextInterval);\n }, currentInterval);\n }, []);\n\n const onPointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (disabled) return;\n // Only primary button (left mouse / single touch / pen)\n if (e.button !== 0 && e.pointerType === \"mouse\") return;\n\n // Fire immediately\n callbackRef.current();\n isHeldRef.current = true;\n\n // After initial delay, start accelerating repeats\n delayTimerRef.current = setTimeout(() => {\n scheduleRepeat(intervalRef.current);\n }, delayRef.current);\n },\n [disabled, scheduleRepeat]\n );\n\n const onPointerUp = useCallback(\n (e: React.PointerEvent) => {\n e.preventDefault();\n clearTimers();\n },\n [clearTimers]\n );\n\n const onPointerLeave = useCallback(\n (e: React.PointerEvent) => {\n void e;\n clearTimers();\n },\n [clearTimers]\n );\n\n // Safety: clear on unmount\n useEffect(() => clearTimers, [clearTimers]);\n\n return { onPointerDown, onPointerUp, onPointerLeave };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { computeNewCursorPosition } from \"../core/cursor.js\";\nimport { createFormatter } from \"../core/formatter.js\";\nimport { localizeDigits, normalizeDigits } from \"../core/normalizer.js\";\nimport { createParser } from \"../core/parser.js\";\nimport type { NumberFieldAria, NumberFieldState, UseNumberFieldProps } from \"../core/types.js\";\nimport { usePressAndHold } from \"./usePressAndHold.js\";\n\n// ── Tiny helper to safely escape regex special chars (including hyphen) ──────\n\nfunction escapeRegex(s: string): string {\n // Escaping hyphen prevents it from being misinterpreted as a range indicator\n // inside a character class (e.g. [.--] would be invalid without this)\n return s.replace(/[.*+?^${}()|[\\]\\\\\\-]/g, \"\\\\$&\");\n}\n\n/**\n * Parse scientific (\"1e3\", \"1.23E4\") and compact (\"1.5K\", \"3.4M\") notation that\n * the plain locale parser cannot handle. Used on paste so values copied from\n * spreadsheets / dashboards round-trip instead of being mangled by char-strip.\n * Returns null when `s` is not one of these forms.\n */\nfunction parseSpecialNotation(s: string): number | null {\n const t = s.replace(/\\s+/g, \"\");\n if (/^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)[eE][+-]?\\d+$/.test(t)) {\n const n = Number(t);\n return Number.isFinite(n) ? n : null;\n }\n const m = t.match(/^([+-]?(?:\\d+\\.?\\d*|\\.\\d+))(k|m|b|t|thousand|million|billion|trillion)$/i);\n if (m) {\n const mult: Record<string, number> = {\n k: 1e3,\n thousand: 1e3,\n m: 1e6,\n million: 1e6,\n b: 1e9,\n billion: 1e9,\n t: 1e12,\n trillion: 1e12,\n };\n const n = Number(m[1]) * mult[m[2].toLowerCase()]!;\n return Number.isFinite(n) ? n : null;\n }\n return null;\n}\n\nexport function useNumberField(\n props: UseNumberFieldProps,\n state: NumberFieldState,\n inputRef: React.RefObject<HTMLInputElement | null>\n): NumberFieldAria {\n const {\n locale,\n formatOptions,\n minValue,\n maxValue,\n allowNegative = true,\n allowDecimal = true,\n allowMouseWheel = false,\n liveFormat: rawLiveFormat = true,\n prefix,\n suffix,\n name,\n disabled,\n readOnly,\n required,\n onFocus,\n onBlur,\n maximumFractionDigits,\n minimumFractionDigits,\n fixedDecimalScale,\n copyBehavior = \"formatted\",\n stepHoldDelay = 400,\n stepHoldInterval = 200,\n formatValue: customFormatValue,\n parseValue: customParseValue,\n onValueCommitted,\n } = props; // formatValue/parseValue are on UseNumberFieldStateOptions (inherited)\n\n // Compact/scientific/engineering notation produce formatted strings (\"2.5K\",\n // \"1.5E3\") whose suffix/exponent characters collide with continued typing, so\n // we keep the raw typed digits live and only format on blur/commit.\n const notation = formatOptions?.notation;\n const liveFormat =\n rawLiveFormat &&\n notation !== \"compact\" &&\n notation !== \"scientific\" &&\n notation !== \"engineering\";\n\n const { step = 1, largeStep = step * 10, smallStep = step * 0.1 } = state.options;\n\n const autoId = useId();\n const inputId = props.id ?? `raqam-${autoId}`;\n const labelId = `${inputId}-label`;\n const descriptionId = `${inputId}-description`;\n const errorId = `${inputId}-error`;\n\n // ── Formatter & parser (kept in sync with state's) ──────────────────────\n // Mirror the state hook: drop fraction padding when decimals are disallowed.\n const effMinFrac = allowDecimal ? minimumFractionDigits : 0;\n const effMaxFrac = allowDecimal ? maximumFractionDigits : 0;\n const effFixedScale = allowDecimal ? fixedDecimalScale : false;\n\n const formatter = useMemo(\n () =>\n createFormatter({\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits: effMinFrac,\n maximumFractionDigits: effMaxFrac,\n fixedDecimalScale: effFixedScale,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [locale, JSON.stringify(formatOptions), prefix, suffix, effMinFrac, effMaxFrac, effFixedScale]\n );\n\n // Live-typing formatter: keeps grouping + currency symbol but drops the\n // minimum-fraction *padding* (\".00\") so currency / fixedDecimalScale fields\n // group correctly while typing and never accumulate padding zeros. The full\n // `formatter` (with padding) is applied on commit/blur.\n //\n // Percent fields default to maximumFractionDigits:0, which would round away\n // the fraction the user is typing (\"12.5\" → \"13%\") and — because the rounded\n // string is shorter — corrupt the next keystroke. Give the percent live\n // formatter room so typing never rounds; commit() rounds to the real scale.\n const isPercentStyle = formatOptions?.style === \"percent\";\n const liveMaxFrac = allowDecimal ? (isPercentStyle ? 20 : effMaxFrac) : 0;\n const liveFormatter = useMemo(\n () =>\n createFormatter({\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits: 0,\n maximumFractionDigits: liveMaxFrac,\n fixedDecimalScale: false,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [locale, JSON.stringify(formatOptions), prefix, suffix, liveMaxFrac]\n );\n\n const parser = useMemo(\n () =>\n createParser({\n locale,\n formatOptions,\n allowNegative,\n allowDecimal,\n prefix,\n suffix,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [locale, JSON.stringify(formatOptions), allowNegative, allowDecimal, prefix, suffix]\n );\n\n // Re-format `value` so its integer part groups while the EXACT typed fraction\n // (incl. trailing zeros) from `source` is preserved. Returns null when there is\n // no integer part (leading-dot \".5\" — keep it raw to avoid a \"0\" prepend that\n // would shift the caret) or no fraction (trailing dot). Used by the typing path\n // and the grouping-comma / trailing-affordance backspace paths so they all\n // preserve typed trailing zeros consistently.\n const formatGroupedFraction = useCallback(\n (value: number, source: string): string | null => {\n const info = formatter.getLocaleInfo();\n let decIdx = source.lastIndexOf(info.decimalSeparator);\n // Fall back to an ASCII \".\" only when it stands in for the decimal point\n // (not when \".\" is the grouping separator, e.g. de-DE — see Fix J).\n if (decIdx === -1 && info.decimalSeparator !== \".\" && info.groupingSeparator !== \".\") {\n decIdx = source.lastIndexOf(\".\");\n }\n if (decIdx === -1) return null;\n if (!/\\d/.test(normalizeDigits(source.slice(0, decIdx)))) return null; // leading dot\n const fracMatch = normalizeDigits(source.slice(decIdx + 1)).match(/^\\d+/);\n if (!fracMatch) return null; // trailing dot\n const fracLen = Math.min(fracMatch[0].length, effMaxFrac ?? 20, 20);\n if (fracLen === 0) return null;\n return createFormatter({\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits: fracLen,\n maximumFractionDigits: fracLen,\n }).format(value);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [formatter, locale, JSON.stringify(formatOptions), prefix, suffix, effMaxFrac]\n );\n\n // ── Cursor engine ────────────────────────────────────────────────────────\n const pendingCursor = useRef<number | null>(null);\n\n // Restore cursor synchronously after React commits the new value to DOM\n useLayoutEffect(() => {\n if (\n pendingCursor.current !== null &&\n inputRef.current &&\n document.activeElement === inputRef.current\n ) {\n inputRef.current.setSelectionRange(pendingCursor.current, pendingCursor.current);\n pendingCursor.current = null;\n }\n // Run after every inputValue change\n }, [state.inputValue, inputRef]);\n\n // ── Mouse wheel (non-passive native listener) ────────────────────────────\n // React's synthetic onWheel is passive in React 17+; it cannot call\n // preventDefault(). We must attach a native, non-passive listener instead.\n useEffect(() => {\n const el = inputRef.current;\n if (!el || !allowMouseWheel) return;\n\n const handler = (e: WheelEvent) => {\n if (disabled || readOnly) return;\n if (document.activeElement !== el) return;\n e.preventDefault();\n state._setLastChangeReason(\"wheel\");\n if (e.deltaY < 0) {\n state.increment();\n } else {\n state.decrement();\n }\n };\n\n el.addEventListener(\"wheel\", handler, { passive: false });\n return () => el.removeEventListener(\"wheel\", handler);\n }, [allowMouseWheel, disabled, readOnly, state, inputRef]);\n\n // ── IME Composition state ────────────────────────────────────────────────\n // During CJK IME input, partial composed characters must not trigger live\n // formatting. We suspend formatting during composition and resume on end.\n const isComposing = useRef(false);\n\n const handleCompositionStart = useCallback(() => {\n isComposing.current = true;\n }, []);\n\n const handleCompositionEnd = useCallback(\n (e: React.CompositionEvent<HTMLInputElement>) => {\n isComposing.current = false;\n // After composition ends, run the full format cycle on the composed value\n const composedValue = e.currentTarget.value;\n const info = formatter.getLocaleInfo();\n const normalized = normalizeDigits(composedValue);\n\n let displayValue: string;\n if (customParseValue) {\n const result = customParseValue(normalized);\n if (result.isIntermediate) {\n displayValue = normalized;\n } else if (result.value !== null && customFormatValue) {\n displayValue = customFormatValue(result.value);\n } else if (result.value !== null) {\n displayValue = formatter.format(result.value);\n } else {\n displayValue = normalized;\n }\n // Disable cursor engine for custom format/parse\n pendingCursor.current = displayValue.length;\n } else if (liveFormat) {\n const result = parser.parse(normalized);\n if (result.isIntermediate) {\n // Keep the still-typing display in the locale's native digit script.\n displayValue = localizeDigits(normalized, info.zero);\n } else if (result.value !== null) {\n displayValue = customFormatValue\n ? customFormatValue(result.value)\n : liveFormatter.format(result.value);\n } else {\n displayValue = normalized === \"\" ? \"\" : normalized;\n }\n pendingCursor.current = computeNewCursorPosition(\n composedValue,\n composedValue.length,\n displayValue,\n info,\n \"insertCompositionText\"\n );\n } else {\n displayValue = normalized;\n pendingCursor.current = normalized.length;\n }\n\n state._setLastChangeReason(\"input\");\n state.setInputValue(displayValue);\n },\n [formatter, liveFormatter, parser, liveFormat, state, customFormatValue, customParseValue]\n );\n\n // ── onChange handler ─────────────────────────────────────────────────────\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const rawInputValue = e.target.value;\n const cursorPos = e.target.selectionStart ?? rawInputValue.length;\n const inputType = (e.nativeEvent as InputEvent).inputType;\n const info = formatter.getLocaleInfo();\n\n // During IME composition, skip live formatting — just track the raw value\n if (isComposing.current) {\n state.setInputValue(rawInputValue);\n return;\n }\n\n // Normalise non-Latin digits\n let normalized = normalizeDigits(rawInputValue);\n\n // Drop characters disallowed by the constraint flags *live*, so the field\n // never shows an invalid string that gets wiped on blur. The minus / dot\n // keys simply do nothing instead of poisoning the value.\n if (!allowNegative) {\n normalized = normalized.split(\"-\").join(\"\").split(info.minusSign).join(\"\");\n }\n if (!allowDecimal) {\n normalized = normalized.split(\".\").join(\"\").split(info.decimalSeparator).join(\"\");\n } else if (info.decimalSeparator !== \".\" && info.groupingSeparator !== \".\") {\n // Latin-keyboard users type the ASCII \".\" as the decimal point even in\n // locales whose separator is non-ASCII (ar/fa: ٫). Map a \".\" that is part\n // of a number (adjacent to a digit) onto the locale separator so the value\n // parses and the caret engine (which only tracks the locale separator)\n // doesn't strand the dot. Dots inside a symbol (e.g. the Arabic currency\n // symbol \"ج.م.\") are NOT adjacent to digits, so they stay untouched.\n // Skipped entirely when \".\" is the grouping separator (e.g. de-DE).\n normalized = normalized.replace(/\\./g, (_m, offset: number, str: string) =>\n /\\d/.test(str[offset - 1] ?? \"\") || /\\d/.test(str[offset + 1] ?? \"\")\n ? info.decimalSeparator\n : \".\"\n );\n }\n\n let displayValue: string;\n let knownValue: number | null | undefined;\n\n // Custom parse/format escape hatch\n if (customParseValue) {\n const result = customParseValue(normalized);\n if (result.isIntermediate) {\n displayValue = normalized;\n } else if (result.value !== null) {\n displayValue = customFormatValue\n ? customFormatValue(result.value)\n : formatter.format(result.value);\n } else if (normalized === \"\") {\n displayValue = \"\";\n } else {\n displayValue = normalized;\n }\n // Can't predict cursor position with custom formatter — place at end\n pendingCursor.current = displayValue.length;\n } else if (liveFormat) {\n const result = parser.parse(normalized);\n\n if (result.isIntermediate) {\n // A trailing-zero decimal (e.g. \"12.50\") is intermediate, but its\n // integer part should still group live (insert \"99\" into \"$12.50\" must\n // show \"$9,912.50\"). Re-format preserving the typed fraction; lone \"-\",\n // trailing \".\" and leading \".\" keep the raw form.\n const grouped =\n !customFormatValue && result.value !== null\n ? formatGroupedFraction(result.value, normalized)\n : null;\n displayValue = grouped ?? localizeDigits(normalized, info.zero);\n } else if (result.value !== null) {\n if (customFormatValue) {\n displayValue = customFormatValue(result.value);\n } else {\n displayValue = liveFormatter.format(result.value);\n // The display will be re-parsed by setInputValue. For invertible\n // formats that round-trips (and rounds the value to the displayed\n // precision); for non-invertible notation (compact \"2.5K\",\n // scientific, unit) re-parsing destroys magnitude — so pass the\n // exact typed value through when the format does not round-trip.\n const rt = parser.parse(displayValue).value;\n knownValue =\n rt !== null && Number.isFinite(rt) && liveFormatter.format(rt) === displayValue\n ? rt\n : result.value;\n }\n } else if (normalized === \"\" || !/\\d/.test(normalized)) {\n // Empty, or only formatting affordances left (a lone \"%\", suffix, etc.\n // after deleting the last digit) — clear the field instead of stranding\n // the orphaned characters.\n displayValue = \"\";\n } else {\n // Invalid input — keep the raw normalised string so the user can\n // see what they typed (they'll get corrected on blur)\n displayValue = normalized;\n }\n\n if (customFormatValue) {\n // Custom format: can't predict cursor, place at end\n pendingCursor.current = displayValue.length;\n } else {\n // Compute and stash cursor position for useLayoutEffect\n pendingCursor.current = computeNewCursorPosition(\n rawInputValue,\n cursorPos,\n displayValue,\n info,\n inputType\n );\n }\n } else {\n // No live format — just pass through normalised digits\n displayValue = normalized;\n pendingCursor.current = cursorPos;\n }\n\n // An edit that empties the field reports the dedicated \"clear\" reason so\n // consumers can distinguish a deletion-to-empty from ordinary typing.\n state._setLastChangeReason(displayValue === \"\" ? \"clear\" : \"input\");\n state.setInputValue(displayValue, knownValue);\n },\n [\n formatter,\n liveFormatter,\n parser,\n liveFormat,\n state,\n customFormatValue,\n customParseValue,\n formatGroupedFraction,\n ]\n );\n\n // ── Paste handler ────────────────────────────────────────────────────────\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n const text = e.clipboardData.getData(\"text/plain\");\n if (!text) return;\n\n // 1. Strip common currency symbols (global currencies)\n const stripped = text.replace(/[€$£¥₹₺₽﷼฿₩¢₦₨₪₫₱]/g, \"\").trim();\n\n // 2. Normalize non-Latin digits to ASCII\n let normalized = normalizeDigits(stripped);\n\n // Honour the constraint flags on paste too (drop minus / decimal).\n if (!allowNegative) {\n const li = formatter.getLocaleInfo();\n normalized = normalized.split(\"-\").join(\"\").split(li.minusSign).join(\"\");\n }\n if (!allowDecimal) {\n const li = formatter.getLocaleInfo();\n normalized = normalized.split(\".\").join(\"\").split(li.decimalSeparator).join(\"\");\n }\n\n state._setLastChangeReason(\"paste\");\n\n // Custom parse escape hatch\n if (customParseValue) {\n const result = customParseValue(normalized);\n if (result.value !== null) {\n const formatted = customFormatValue\n ? customFormatValue(result.value)\n : formatter.format(result.value);\n // Pass the known value so a non-invertible format (compact/scientific)\n // is not re-parsed into a wrong magnitude.\n state.setInputValue(formatted, result.value);\n pendingCursor.current = formatted.length;\n }\n return;\n }\n\n // 2.5 Scientific / compact notation (1e3, 1.23E4, 1.5K…) before the\n // locale parser, whose char-strip would otherwise mangle the e / K.\n const special = parseSpecialNotation(normalized);\n if (special !== null) {\n const isPercent = formatOptions?.style === \"percent\";\n const sval = isPercent ? special / 100 : special;\n const formatted = customFormatValue ? customFormatValue(sval) : formatter.format(sval);\n state.setInputValue(formatted, sval);\n pendingCursor.current = formatted.length;\n return;\n }\n\n // 3. Try parse with current locale parser\n const result = parser.parse(normalized);\n\n if (result.value !== null) {\n const formatted = formatter.format(result.value);\n state.setInputValue(formatted, result.value);\n pendingCursor.current = formatted.length;\n return;\n }\n\n // 4. Fallback: strip everything except digits, locale decimal, minus sign\n const localeInfo = formatter.getLocaleInfo();\n const allowedCharsPattern = new RegExp(\n `[^0-9${escapeRegex(localeInfo.decimalSeparator)}${escapeRegex(localeInfo.minusSign)}-]`,\n \"g\"\n );\n const stripped2 = normalized.replace(allowedCharsPattern, \"\");\n const result2 = parser.parse(stripped2);\n\n if (result2.value !== null) {\n const formatted = formatter.format(result2.value);\n state.setInputValue(formatted, result2.value);\n pendingCursor.current = formatted.length;\n }\n // If still invalid, silently discard — don't paste garbage into the field\n },\n [parser, formatter, state, customFormatValue, customParseValue]\n );\n\n // ── Copy / Cut handlers ──────────────────────────────────────────────────\n const handleCopy = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n if (copyBehavior === \"formatted\") return; // browser handles it natively\n\n e.preventDefault();\n const text = String(state.numberValue ?? \"\");\n e.clipboardData.setData(\"text/plain\", text);\n },\n [copyBehavior, state.numberValue]\n );\n\n const handleCut = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n if (copyBehavior === \"formatted\") return; // browser handles it\n\n e.preventDefault();\n const text = String(state.numberValue ?? \"\");\n e.clipboardData.setData(\"text/plain\", text);\n // Clear the field after cut — report the dedicated \"clear\" reason.\n state._setLastChangeReason(\"clear\");\n state.setInputValue(\"\");\n },\n [copyBehavior, state]\n );\n\n // ── Keyboard handler ─────────────────────────────────────────────────────\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (disabled || readOnly) return;\n\n const key = e.key;\n\n // Smart backspace: when cursor is immediately after a grouping separator\n // (no selection active, no modifier keys), delete both the separator and\n // the preceding digit so the user can backspace through formatted numbers\n // without the comma \"blocking\" deletion.\n //\n // This must be handled in keydown — by the time onChange fires, the\n // browser has already removed the separator character, making it\n // impossible to detect what was deleted.\n // Smart decimal: when the user types the decimal separator but one already\n // exists in the formatted value (e.g. \"1.00\" with fixedDecimalScale),\n // move the cursor to just after the decimal separator instead of inserting\n // a duplicate. This enables the financial UX pattern:\n // \"1.00\" → type \".\" → cursor jumps after \".\" → type \"5\" → \"1.50\"\n // Same applies for negative values: \"-1.00\" → type \".\" → cursor after \".\"\n if (!e.metaKey && !e.ctrlKey && !e.altKey && allowDecimal) {\n const localeInfo = formatter.getLocaleInfo();\n // Match the locale's decimal separator key (e.g. \".\" for en-US, \",\" for\n // de-DE), plus the ASCII \".\" when it stands in for a non-ASCII separator\n // (ar/fa). Do NOT match \".\" when it is the grouping separator (de-DE).\n const isDecimalKey =\n key === localeInfo.decimalSeparator ||\n (key === \".\" &&\n localeInfo.decimalSeparator !== \".\" &&\n localeInfo.groupingSeparator !== \".\");\n if (isDecimalKey) {\n const input = inputRef.current;\n if (input) {\n const decPos = input.value.indexOf(localeInfo.decimalSeparator);\n if (decPos !== -1) {\n e.preventDefault();\n input.setSelectionRange(decPos + 1, decPos + 1);\n return;\n }\n }\n }\n }\n\n if (key === \"Backspace\" && !e.shiftKey && !e.altKey && !e.metaKey && !e.ctrlKey) {\n const input = inputRef.current;\n if (input) {\n const cursor = input.selectionStart ?? 0;\n const selEnd = input.selectionEnd ?? cursor;\n const currentValue = input.value;\n const info = formatter.getLocaleInfo();\n\n if (\n cursor === selEnd && // no text selection — single caret\n cursor >= 2 &&\n currentValue[cursor - 1] === info.groupingSeparator\n ) {\n e.preventDefault();\n // Remove the grouping separator (cursor-1) AND the digit before it (cursor-2)\n const rawEdited = currentValue.slice(0, cursor - 2) + currentValue.slice(cursor);\n const parseResult = parser.parse(rawEdited);\n\n state._setLastChangeReason(\"input\");\n let nextDisplay: string;\n if (parseResult.value !== null) {\n // Preserve typed trailing zeros; use the LIVE formatter (no\n // min-fraction padding) so editing matches the typing display.\n nextDisplay =\n formatGroupedFraction(parseResult.value, rawEdited) ??\n liveFormatter.format(parseResult.value);\n state.setInputValue(nextDisplay, parseResult.value);\n } else {\n // Empty or intermediate — store as-is (blur will clean up). If the\n // edit emptied the field, report the dedicated \"clear\" reason.\n nextDisplay = rawEdited;\n if (rawEdited === \"\") state._setLastChangeReason(\"clear\");\n state.setInputValue(rawEdited);\n }\n // Remap the caret through the cursor engine so re-grouping shifts\n // (e.g. \"1,234,567\" → \"123,567\") never leave it stranded after a comma.\n pendingCursor.current = computeNewCursorPosition(\n rawEdited,\n cursor - 2,\n nextDisplay,\n info,\n \"deleteContentBackward\"\n );\n return;\n }\n\n // Backspace over a trailing affordance (% sign, suffix like \" kg\") —\n // the browser would delete the affordance char, but the formatter\n // immediately re-appends it, so the field never changes. Instead delete\n // the digit that precedes the affordance run. Digit detection is\n // script-aware (\\p{Nd}) so it works for native digits (fa/ar) too.\n const isDigitChar = (ch: string | undefined): boolean =>\n ch !== undefined && /\\p{Nd}/u.test(ch);\n const isAffordanceChar = (ch: string | undefined): boolean =>\n ch !== undefined &&\n !isDigitChar(ch) &&\n ch !== info.decimalSeparator &&\n ch !== info.minusSign &&\n ch !== \"-\";\n if (\n cursor === selEnd &&\n cursor === currentValue.length &&\n cursor >= 1 &&\n isAffordanceChar(currentValue[cursor - 1])\n ) {\n // Walk back over the trailing affordance run to the last real char.\n let i = cursor;\n while (i > 0 && isAffordanceChar(currentValue[i - 1])) i--;\n if (i > 0 && isDigitChar(currentValue[i - 1])) {\n e.preventDefault();\n const rawEdited = currentValue.slice(0, i - 1) + currentValue.slice(i);\n const parseResult = parser.parse(rawEdited);\n state._setLastChangeReason(\"input\");\n let nextDisplay: string;\n if (parseResult.value !== null && /\\p{Nd}/u.test(rawEdited)) {\n // Use the LIVE formatter (no min-fraction padding) so the display\n // matches the typing path — never re-pad \".00\" mid-edit.\n nextDisplay =\n formatGroupedFraction(parseResult.value, rawEdited) ??\n liveFormatter.format(parseResult.value);\n state.setInputValue(nextDisplay, parseResult.value);\n } else {\n // No digits left — clear the field (don't strand the affordance).\n // Report the dedicated \"clear\" reason like the onChange path.\n nextDisplay = \"\";\n state._setLastChangeReason(\"clear\");\n state.setInputValue(\"\");\n }\n pendingCursor.current = computeNewCursorPosition(\n rawEdited,\n i - 1,\n nextDisplay,\n info,\n \"deleteContentBackward\"\n );\n return;\n }\n }\n }\n }\n\n if (key === \"ArrowUp\" || key === \"ArrowDown\") {\n e.preventDefault();\n const direction = key === \"ArrowUp\" ? 1 : -1;\n state._setLastChangeReason(\"keyboard\");\n if (e.shiftKey) {\n direction > 0 ? state.increment(largeStep) : state.decrement(largeStep);\n } else if (e.metaKey || e.ctrlKey) {\n direction > 0 ? state.increment(smallStep) : state.decrement(smallStep);\n } else {\n direction > 0 ? state.increment() : state.decrement();\n }\n return;\n }\n\n if (key === \"PageUp\") {\n e.preventDefault();\n state._setLastChangeReason(\"keyboard\");\n state.increment(largeStep);\n return;\n }\n\n if (key === \"PageDown\") {\n e.preventDefault();\n state._setLastChangeReason(\"keyboard\");\n state.decrement(largeStep);\n return;\n }\n\n if (key === \"Home\") {\n if (minValue !== undefined) {\n e.preventDefault();\n state._setLastChangeReason(\"keyboard\");\n state.decrementToMin();\n }\n return;\n }\n\n if (key === \"End\") {\n if (maxValue !== undefined) {\n e.preventDefault();\n state._setLastChangeReason(\"keyboard\");\n state.incrementToMax();\n }\n return;\n }\n\n if (key === \"Enter\") {\n state._setLastChangeReason(\"blur\");\n const committed = state.commit();\n onValueCommitted?.(committed, { reason: \"keyboard\" });\n return;\n }\n },\n [\n disabled,\n readOnly,\n state,\n largeStep,\n smallStep,\n minValue,\n maxValue,\n formatter,\n liveFormatter,\n parser,\n inputRef,\n allowDecimal,\n formatGroupedFraction,\n onValueCommitted,\n ]\n );\n\n // ── Blur handler ─────────────────────────────────────────────────────────\n const handleBlur = useCallback(\n (e: React.FocusEvent<HTMLInputElement>) => {\n state.setIsFocused(false);\n state._setLastChangeReason(\"blur\");\n const committed = state.commit();\n onValueCommitted?.(committed, { reason: \"blur\" });\n onBlur?.(e);\n },\n [state, onBlur, onValueCommitted]\n );\n\n // ── Focus handler ────────────────────────────────────────────────────────\n const handleFocus = useCallback(\n (e: React.FocusEvent<HTMLInputElement>) => {\n state.setIsFocused(true);\n onFocus?.(e);\n },\n [state, onFocus]\n );\n\n // ── Press-and-hold for increment/decrement buttons ───────────────────────\n const incrementHold = usePressAndHold(\n () => {\n state._setLastChangeReason(\"increment\");\n state.increment();\n },\n {\n delay: stepHoldDelay,\n interval: stepHoldInterval,\n disabled: disabled || !state.canIncrement,\n }\n );\n\n const decrementHold = usePressAndHold(\n () => {\n state._setLastChangeReason(\"decrement\");\n state.decrement();\n },\n {\n delay: stepHoldDelay,\n interval: stepHoldInterval,\n disabled: disabled || !state.canDecrement,\n }\n );\n\n // ── ARIA valuetext ───────────────────────────────────────────────────────\n const ariaValueText = useMemo(() => {\n if (state.numberValue == null) return undefined;\n return customFormatValue\n ? customFormatValue(state.numberValue)\n : formatter.format(state.numberValue);\n }, [state.numberValue, formatter, customFormatValue]);\n\n // ── RTL detection ────────────────────────────────────────────────────────\n const localeInfo = formatter.getLocaleInfo();\n\n // ── Out-of-range + validation detection (for aria-invalid + data-invalid) ─\n const isOutOfRange =\n state.numberValue !== null &&\n ((minValue !== undefined && state.numberValue < minValue) ||\n (maxValue !== undefined && state.numberValue > maxValue));\n\n const isInvalid = isOutOfRange || state.validationState === \"invalid\";\n\n // ── Prop maps ────────────────────────────────────────────────────────────\n\n // Track whether a label element is actually mounted. `labelProps.ref` (below)\n // registers/unregisters as it mounts, so `aria-labelledby` only points at the\n // label when it truly exists — for any render path (built-in component, custom\n // primitive, or fully headless), not just one that runs a specific effect.\n const labelCountRef = useRef(0);\n const [hasLabel, setHasLabel] = useState(false);\n const labelRef = useCallback<React.RefCallback<HTMLElement>>((node) => {\n if (node) {\n labelCountRef.current += 1;\n setHasLabel(true);\n } else if (labelCountRef.current > 0) {\n labelCountRef.current -= 1;\n if (labelCountRef.current === 0) setHasLabel(false);\n }\n }, []);\n\n // Fall back to the internal label id only when the consumer hasn't supplied\n // their own accessible name AND a label is actually rendered. Defaulting to\n // `labelId` otherwise points `aria-labelledby` at a `<label>` that may not\n // exist (e.g. when only `aria-label` is passed), producing a dangling ref.\n const ariaLabelledBy =\n props[\"aria-labelledby\"] ?? (props[\"aria-label\"] ? undefined : hasLabel ? labelId : undefined);\n\n const labelProps: NumberFieldAria[\"labelProps\"] = {\n id: labelId,\n htmlFor: inputId,\n ref: labelRef,\n };\n\n const groupProps: React.HTMLAttributes<HTMLDivElement> = {\n role: \"group\",\n \"aria-labelledby\": ariaLabelledBy,\n };\n\n const inputProps: React.InputHTMLAttributes<HTMLInputElement> = {\n id: inputId,\n type: \"text\",\n inputMode: \"decimal\",\n role: \"spinbutton\",\n autoComplete: \"off\",\n autoCorrect: \"off\",\n spellCheck: false,\n \"aria-label\": props[\"aria-label\"],\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": props[\"aria-describedby\"],\n \"aria-valuenow\": state.numberValue ?? undefined,\n \"aria-valuemin\": minValue,\n \"aria-valuemax\": maxValue,\n \"aria-valuetext\": ariaValueText,\n \"aria-disabled\": disabled || undefined,\n \"aria-readonly\": readOnly || undefined,\n \"aria-required\": required || undefined,\n \"aria-invalid\": isInvalid ? true : undefined,\n \"aria-errormessage\": isInvalid && state.validationError ? errorId : undefined,\n disabled,\n readOnly,\n required,\n value: state.inputValue,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n onBlur: handleBlur,\n onFocus: handleFocus,\n onPaste: handlePaste,\n onCopy: copyBehavior !== \"formatted\" ? handleCopy : undefined,\n onCut: copyBehavior !== \"formatted\" ? handleCut : undefined,\n onCompositionStart: handleCompositionStart,\n onCompositionEnd: handleCompositionEnd,\n // RTL: numbers are always LTR, align-right in RTL contexts\n // unicodeBidi: embed isolates the LTR number from surrounding RTL text\n style: localeInfo.isRTL\n ? { direction: \"ltr\", textAlign: \"right\", unicodeBidi: \"embed\" }\n : undefined,\n // Data attributes for CSS styling\n \"data-disabled\": disabled ? \"\" : undefined,\n \"data-readonly\": readOnly ? \"\" : undefined,\n \"data-required\": required ? \"\" : undefined,\n \"data-invalid\": isInvalid ? \"\" : undefined,\n \"data-rtl\": localeInfo.isRTL ? \"\" : undefined,\n } as React.InputHTMLAttributes<HTMLInputElement>;\n\n const hiddenInputProps: React.InputHTMLAttributes<HTMLInputElement> | null = name\n ? {\n type: \"hidden\",\n name,\n value: state.numberValue ?? \"\",\n \"aria-hidden\": true,\n }\n : null;\n\n const incrementButtonProps: React.ButtonHTMLAttributes<HTMLButtonElement> = {\n type: \"button\",\n tabIndex: -1,\n \"aria-label\": \"Increase\",\n disabled: disabled || !state.canIncrement,\n // Press-and-hold handlers replace simple onClick\n ...incrementHold,\n \"data-disabled\": disabled || !state.canIncrement ? \"\" : undefined,\n } as React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n const decrementButtonProps: React.ButtonHTMLAttributes<HTMLButtonElement> = {\n type: \"button\",\n tabIndex: -1,\n \"aria-label\": \"Decrease\",\n disabled: disabled || !state.canDecrement,\n // Press-and-hold handlers replace simple onClick\n ...decrementHold,\n \"data-disabled\": disabled || !state.canDecrement ? \"\" : undefined,\n } as React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n const descriptionProps: React.HTMLAttributes<HTMLElement> = {\n id: descriptionId,\n };\n\n const errorMessageProps: React.HTMLAttributes<HTMLElement> = {\n id: errorId,\n role: \"alert\",\n \"aria-live\": \"polite\",\n } as React.HTMLAttributes<HTMLElement>;\n\n return {\n labelProps,\n groupProps,\n inputProps,\n hiddenInputProps,\n incrementButtonProps,\n decrementButtonProps,\n descriptionProps,\n errorMessageProps,\n };\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { createFormatter } from \"../core/formatter.js\";\nimport type { UseNumberFieldStateOptions } from \"../core/types.js\";\n\ntype FormatOptions = Pick<\n UseNumberFieldStateOptions,\n | \"locale\"\n | \"formatOptions\"\n | \"prefix\"\n | \"suffix\"\n | \"minimumFractionDigits\"\n | \"maximumFractionDigits\"\n | \"fixedDecimalScale\"\n>;\n\n/**\n * Lightweight display-only formatting hook. Returns the formatted string for\n * a numeric value using the same Intl.NumberFormat engine as the full input.\n *\n * Use this when you need to display a formatted number in a read-only context\n * (table cells, summaries, labels) without the overhead of a full input state machine.\n *\n * @example\n * const price = useNumberFieldFormat(1234567.89, {\n * locale: 'en-US',\n * formatOptions: { style: 'currency', currency: 'USD' },\n * })\n * // price === \"$1,234,567.89\"\n *\n * @example\n * const pct = useNumberFieldFormat(0.4267, {\n * formatOptions: { style: 'percent', maximumFractionDigits: 1 },\n * })\n * // pct === \"42.7%\"\n */\nexport function useNumberFieldFormat(value: number | null, options: FormatOptions = {}): string {\n const {\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits,\n maximumFractionDigits,\n fixedDecimalScale,\n } = options;\n\n const formatter = useMemo(\n () =>\n createFormatter({\n locale,\n formatOptions,\n prefix,\n suffix,\n minimumFractionDigits,\n maximumFractionDigits,\n fixedDecimalScale,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n locale,\n JSON.stringify(formatOptions),\n prefix,\n suffix,\n minimumFractionDigits,\n maximumFractionDigits,\n fixedDecimalScale,\n ]\n );\n\n return useMemo(() => {\n if (value === null || value === undefined) return \"\";\n return formatter.format(value);\n }, [value, formatter]);\n}\n","import { createContext, useContext } from \"react\";\nimport type { RefObject } from \"react\";\nimport type { NumberFieldAria, NumberFieldState, UseNumberFieldProps } from \"../core/types.js\";\n\nexport interface NumberFieldContextValue {\n state: NumberFieldState;\n aria: NumberFieldAria;\n inputRef: RefObject<HTMLInputElement | null>;\n props: UseNumberFieldProps;\n}\n\nexport const NumberFieldContext = createContext<NumberFieldContextValue | null>(null);\n\n/**\n * Hook for sub-components to access the NumberField context.\n * Throws if used outside NumberField.Root.\n */\nexport function useNumberFieldContext(): NumberFieldContextValue {\n const ctx = useContext(NumberFieldContext);\n if (!ctx) {\n throw new Error(\"[raqam] NumberField sub-components must be used inside <NumberField.Root>.\");\n }\n return ctx;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { NumberFieldState, ScrubAreaOptions } from \"../core/types.js\";\n\nexport interface ScrubAreaReturn {\n /** Whether pointer lock is currently active */\n isScrubbing: boolean;\n /** Props to spread on the scrub area element */\n scrubAreaProps: {\n role: string;\n tabIndex: number;\n style: React.CSSProperties;\n \"aria-label\": string;\n \"data-scrubbing\": string | undefined;\n onPointerDown: (e: React.PointerEvent) => void;\n onKeyDown: (e: React.KeyboardEvent) => void;\n };\n /**\n * Virtual cursor position (screen coordinates, updated by mousemove\n * during pointer lock). Use for positioning the ScrubAreaCursor.\n */\n virtualCursor: { x: number; y: number };\n}\n\n/**\n * Implements Pointer Lock API–based drag-to-scrub behavior.\n *\n * Flow:\n * 1. User presses pointer down → element requests pointer lock\n * 2. Browser hides cursor, starts delivering movementX/Y on mousemove\n * 3. Accumulated movement ÷ pixelSensitivity → increment/decrement calls\n * 4. Pointer lock exits on Escape key or programmatic exit\n */\nexport function useScrubArea(\n state: NumberFieldState,\n options: ScrubAreaOptions = {}\n): ScrubAreaReturn {\n const { direction = \"horizontal\", pixelSensitivity = 4 } = options;\n\n const [isScrubbing, setIsScrubbingLocal] = useState(false);\n\n // Keep stable refs to avoid stale closures in event listeners\n const stateRef = useRef(state);\n stateRef.current = state;\n\n const directionRef = useRef(direction);\n directionRef.current = direction;\n\n const sensitivityRef = useRef(pixelSensitivity);\n sensitivityRef.current = pixelSensitivity;\n\n const isScrubbingRef = useRef(false);\n const accumulatorRef = useRef(0);\n const elementRef = useRef<Element | null>(null);\n const virtualCursorRef = useRef({ x: 0, y: 0 });\n const [virtualCursor, setVirtualCursor] = useState({ x: 0, y: 0 });\n\n // Stable mousemove handler (always reads latest state via refs)\n const stableMouseMove = useRef((e: MouseEvent) => {\n if (!isScrubbingRef.current) return;\n\n // Update virtual cursor\n const nx = virtualCursorRef.current.x + e.movementX;\n const ny = virtualCursorRef.current.y + e.movementY;\n virtualCursorRef.current = { x: nx, y: ny };\n setVirtualCursor({ x: nx, y: ny });\n\n // Determine delta based on direction\n const dir = directionRef.current;\n let delta = 0;\n if (dir === \"horizontal\") {\n delta = e.movementX;\n } else if (dir === \"vertical\") {\n delta = -e.movementY;\n } else {\n delta = Math.abs(e.movementX) >= Math.abs(e.movementY) ? e.movementX : -e.movementY;\n }\n\n accumulatorRef.current += delta;\n\n // Fire step when accumulated movement exceeds sensitivity\n const sensitivity = sensitivityRef.current;\n while (accumulatorRef.current >= sensitivity) {\n stateRef.current.increment();\n accumulatorRef.current -= sensitivity;\n }\n while (accumulatorRef.current <= -sensitivity) {\n stateRef.current.decrement();\n accumulatorRef.current += sensitivity;\n }\n });\n\n // Stable pointer lock change handler\n const stablePointerLockChange = useRef(() => {\n if (document.pointerLockElement === elementRef.current) {\n // Lock acquired — start scrubbing\n isScrubbingRef.current = true;\n accumulatorRef.current = 0;\n setIsScrubbingLocal(true);\n stateRef.current.setIsScrubbing(true);\n document.addEventListener(\"mousemove\", stableMouseMove.current);\n } else {\n // Lock released — stop scrubbing\n isScrubbingRef.current = false;\n accumulatorRef.current = 0;\n document.removeEventListener(\"mousemove\", stableMouseMove.current);\n setIsScrubbingLocal(false);\n stateRef.current.setIsScrubbing(false);\n }\n });\n\n // Register stable pointerlockchange listener once on mount\n useEffect(() => {\n const handler = stablePointerLockChange.current;\n document.addEventListener(\"pointerlockchange\", handler);\n return () => {\n document.removeEventListener(\"pointerlockchange\", handler);\n document.removeEventListener(\"mousemove\", stableMouseMove.current);\n };\n }, []); // Empty deps — truly stable refs, no need to re-register\n\n const onPointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (stateRef.current.options.disabled || stateRef.current.options.readOnly) return;\n if (e.button !== 0) return;\n\n const el = e.currentTarget as HTMLElement;\n elementRef.current = el;\n virtualCursorRef.current = { x: e.clientX, y: e.clientY };\n setVirtualCursor({ x: e.clientX, y: e.clientY });\n\n el.requestPointerLock();\n },\n [] // No deps — reads via refs\n );\n\n // Keyboard support: arrow keys while scrub area is focused\n const onKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (stateRef.current.options.disabled || stateRef.current.options.readOnly) return;\n if (e.key === \"ArrowRight\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n stateRef.current.increment();\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowDown\") {\n e.preventDefault();\n stateRef.current.decrement();\n }\n }, []);\n\n // Cursor CSS based on direction\n const cursorStyle =\n direction === \"horizontal\" ? \"ew-resize\" : direction === \"vertical\" ? \"ns-resize\" : \"move\";\n\n const scrubAreaProps = {\n role: \"slider\",\n tabIndex: state.options.disabled ? -1 : 0,\n style: {\n cursor: state.options.disabled ? undefined : cursorStyle,\n userSelect: \"none\" as const,\n WebkitUserSelect: \"none\" as const,\n } satisfies React.CSSProperties,\n \"aria-label\": \"Scrub to change value\",\n \"data-scrubbing\": isScrubbing ? \"\" : undefined,\n onPointerDown,\n onKeyDown,\n };\n\n return { isScrubbing, scrubAreaProps, virtualCursor };\n}\n","\"use client\";\n\nimport React, { forwardRef, useMemo, useRef } from \"react\";\nimport type {\n NumberFieldRootProps,\n NumberFieldState,\n RenderProp,\n ScrubAreaCursorProps,\n ScrubAreaProps,\n} from \"../core/types.js\";\nimport { NumberFieldContext, useNumberFieldContext } from \"./context.js\";\nimport { useNumberField } from \"./useNumberField.js\";\nimport { useNumberFieldState } from \"./useNumberFieldState.js\";\nimport { useScrubArea } from \"./useScrubArea.js\";\n\n// ── Render prop utility ───────────────────────────────────────────────────────\n\n/**\n * Merge component props with a `render` prop.\n * Accepts either a React element or a render function.\n *\n * `forwardedRef` is threaded through explicitly because React 18 keeps `ref`\n * out of `element.props`, so a render-prop element would otherwise lose refs the\n * default element depends on — e.g. the label-registration ref carried by\n * `labelProps`. When provided, it takes precedence over the render element's own\n * `ref`; callers that need to keep a consumer ref must compose it into\n * `forwardedRef` themselves (see `<NumberField.Label>`), where it can be\n * memoized for a stable identity.\n */\nfunction renderWith(\n defaultElement: React.ReactElement,\n render: RenderProp | undefined,\n state: NumberFieldState,\n forwardedRef?: React.Ref<unknown>\n): React.ReactElement {\n if (!render) return defaultElement;\n\n const baseProps = { ...(defaultElement.props as Record<string, unknown>) };\n if (forwardedRef != null) baseProps.ref = forwardedRef;\n\n if (typeof render === \"function\") {\n return render(baseProps, state);\n }\n\n // Element form: clone with merged props.\n const merged = Object.assign({}, baseProps, render.props as Record<string, unknown>);\n if (forwardedRef != null) merged.ref = forwardedRef;\n return React.cloneElement(render, merged);\n}\n\n// ── Ref helpers ───────────────────────────────────────────────────────────────\n\n// React 19 exposes a React element's `ref` as a regular prop; React ≤18 stores\n// it on the element itself (and reading `element.ref` on React 19 logs a\n// deprecation warning), so branch on the version to read it without warnings.\n// The same version boundary marks where callback refs may return a cleanup\n// function: React 19 runs it on detach, React ≤18 ignores it (and warns).\nconst REF_IN_PROPS = Number.parseInt(React.version, 10) >= 19;\nconst SUPPORTS_REF_CLEANUP = REF_IN_PROPS;\n\nfunction getElementRef(el: React.ReactElement): React.Ref<unknown> | undefined {\n if (REF_IN_PROPS) return (el.props as { ref?: React.Ref<unknown> }).ref;\n return (el as unknown as { ref?: React.Ref<unknown> }).ref;\n}\n\n/**\n * Compose multiple refs (callback or object) into one callback ref while\n * preserving each ref's cleanup. For every ref we capture a cleanup — a function\n * ref's returned cleanup, a synthesized `ref(null)` for legacy refs, or\n * `current = null` for object refs — so consumer cleanups aren't dropped on\n * unmount or ref change.\n *\n * The two React eras differ in HOW the combined cleanup gets back to React:\n * - React 19 runs a cleanup returned from a callback ref, so we return one.\n * - React ≤18 ignores (and warns about) a returned function and instead calls\n * the ref with `null` on detach, so we stash the cleanups in a closure and run\n * them on that `null` call rather than returning a function.\n */\nfunction mergeRefs<T>(...refs: (React.Ref<T> | undefined)[]): React.RefCallback<T> {\n const attach = (node: T | null): (() => void)[] => {\n const cleanups: (() => void)[] = [];\n for (const ref of refs) {\n if (ref == null) continue;\n if (typeof ref === \"function\") {\n const result = ref(node);\n cleanups.push(typeof result === \"function\" ? result : () => ref(null));\n } else {\n (ref as React.MutableRefObject<T | null>).current = node;\n cleanups.push(() => {\n (ref as React.MutableRefObject<T | null>).current = null;\n });\n }\n }\n return cleanups;\n };\n\n if (SUPPORTS_REF_CLEANUP) {\n return (node) => {\n const cleanups = attach(node);\n return () => {\n for (const cleanup of cleanups) cleanup();\n };\n };\n }\n\n // React ≤18: drive cleanups off the `null` detach call instead of a return.\n let cleanups: (() => void)[] = [];\n return (node) => {\n for (const cleanup of cleanups) cleanup();\n cleanups = node == null ? [] : attach(node);\n };\n}\n\n// ── Data attributes helper ────────────────────────────────────────────────────\n\nfunction stateDataAttrs(\n state: NumberFieldState,\n isInvalid: boolean\n): Record<string, string | undefined> {\n const { options } = state;\n return {\n \"data-disabled\": options.disabled ? \"\" : undefined,\n \"data-readonly\": options.readOnly ? \"\" : undefined,\n \"data-required\": options.required ? \"\" : undefined,\n \"data-scrubbing\": state.isScrubbing ? \"\" : undefined,\n \"data-focused\": state.isFocused ? \"\" : undefined,\n \"data-invalid\": isInvalid ? \"\" : undefined,\n };\n}\n\n// ── Root ──────────────────────────────────────────────────────────────────────\n\n// HTML attributes that belong on the wrapper div (not passed to state/aria hooks)\nconst DIV_ONLY_KEYS = new Set([\n \"className\",\n \"style\",\n \"id\",\n \"tabIndex\",\n \"title\",\n \"role\",\n \"aria-label\",\n \"data-testid\",\n \"onClick\",\n \"onMouseEnter\",\n \"onMouseLeave\",\n]);\n\nfunction splitProps(props: Record<string, unknown>) {\n const fieldProps: Record<string, unknown> = {};\n const divProps: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(props)) {\n if (DIV_ONLY_KEYS.has(key) || key.startsWith(\"data-\") || key.startsWith(\"aria-\")) {\n divProps[key] = val;\n } else {\n fieldProps[key] = val;\n }\n }\n return { fieldProps, divProps };\n}\n\nconst Root = forwardRef<HTMLDivElement, NumberFieldRootProps>(function NumberFieldRoot(\n { children, onValueChange, onValueCommitted, ...allProps },\n ref\n) {\n const inputRef = useRef<HTMLInputElement>(null);\n const { fieldProps, divProps } = splitProps(allProps as Record<string, unknown>);\n const props = fieldProps as Omit<\n NumberFieldRootProps,\n \"children\" | \"onValueChange\" | \"onValueCommitted\"\n >;\n\n // Keep a stable ref to onValueChange so the onChange closure never goes stale\n const onValueChangeRef = useRef(onValueChange);\n onValueChangeRef.current = onValueChange;\n\n // Keep a stable ref to the state object so onChange can read the current reason\n const stateRef = useRef<NumberFieldState | null>(null);\n\n // Wrap onChange to also fire onValueChange with the tracked reason.\n // This closure captures stateRef (stable) not state (changes each render).\n // _setLastChangeReason is called synchronously BEFORE the state mutation\n // that triggers onChange, so stateRef.current._getLastChangeReason() always\n // returns the correct reason at the time onChange fires.\n const wrappedProps = {\n ...props,\n // Forward onValueCommitted to the behavior hook, which fires it on blur/Enter.\n onValueCommitted,\n onChange: (value: number | null) => {\n props.onChange?.(value);\n if (onValueChangeRef.current && stateRef.current) {\n onValueChangeRef.current(value, {\n reason: stateRef.current._getLastChangeReason(),\n formattedValue: stateRef.current.inputValue,\n });\n }\n },\n };\n\n const state = useNumberFieldState(wrappedProps);\n stateRef.current = state; // always keep stateRef pointing to current state\n\n const aria = useNumberField(wrappedProps, state, inputRef);\n\n // Determine if field is invalid (out-of-range or failed validate)\n const isInvalid =\n state.validationState === \"invalid\" ||\n (state.numberValue !== null &&\n ((props.minValue !== undefined && state.numberValue < props.minValue) ||\n (props.maxValue !== undefined && state.numberValue > props.maxValue)));\n\n return (\n <NumberFieldContext.Provider value={{ state, aria, inputRef, props: wrappedProps }}>\n <div\n ref={ref}\n {...(divProps as React.HTMLAttributes<HTMLDivElement>)}\n {...stateDataAttrs(state, isInvalid)}\n >\n {children}\n </div>\n </NumberFieldContext.Provider>\n );\n});\n\n// ── Label ─────────────────────────────────────────────────────────────────────\n\ninterface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {\n render?: RenderProp;\n children?: React.ReactNode;\n}\n\nconst Label = forwardRef<HTMLLabelElement, LabelProps>(function NumberFieldLabel(\n { render, children, ...rest },\n ref\n) {\n const { aria, state } = useNumberFieldContext();\n // labelProps carries a registration ref; merge it with the forwarded ref and,\n // for the element render-prop form, the consumer's own ref on that element, so\n // all fire (the registration is what keeps Input/Group's aria-labelledby).\n // Memoized for a stable identity so React doesn't detach/reattach (and re-run\n // ref cleanups) every render — including across the hasLabel re-render.\n const { ref: labelRef, ...labelProps } = aria.labelProps;\n const renderRef = React.isValidElement(render) ? getElementRef(render) : undefined;\n const mergedRef = useMemo(() => mergeRefs(ref, labelRef, renderRef), [ref, labelRef, renderRef]);\n const el = (\n <label ref={mergedRef} {...labelProps} {...rest}>\n {children}\n </label>\n );\n return renderWith(el, render, state, mergedRef);\n});\n\n// ── Group ─────────────────────────────────────────────────────────────────────\n\ninterface GroupProps extends React.HTMLAttributes<HTMLDivElement> {\n render?: RenderProp;\n children?: React.ReactNode;\n}\n\nconst Group = forwardRef<HTMLDivElement, GroupProps>(function NumberFieldGroup(\n { render, children, ...rest },\n ref\n) {\n const { aria, state } = useNumberFieldContext();\n const el = (\n <div ref={ref} {...aria.groupProps} {...rest}>\n {children}\n </div>\n );\n return renderWith(el, render, state);\n});\n\n// ── Input ─────────────────────────────────────────────────────────────────────\n\ninterface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n render?: RenderProp;\n}\n\nconst Input = forwardRef<HTMLInputElement, InputProps>(function NumberFieldInput(\n { render, ...rest },\n _ref\n) {\n const { aria, state, inputRef } = useNumberFieldContext();\n const el = (\n <input ref={inputRef as React.RefObject<HTMLInputElement>} {...aria.inputProps} {...rest} />\n );\n return renderWith(el, render, state);\n});\n\n// ── Increment ─────────────────────────────────────────────────────────────────\n\ninterface IncrementProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n render?: RenderProp;\n children?: React.ReactNode;\n}\n\nconst Increment = forwardRef<HTMLButtonElement, IncrementProps>(function NumberFieldIncrement(\n { render, children, ...rest },\n ref\n) {\n const { aria, state } = useNumberFieldContext();\n const el = (\n <button ref={ref} {...aria.incrementButtonProps} {...rest}>\n {children ?? \"+\"}\n </button>\n );\n return renderWith(el, render, state);\n});\n\n// ── Decrement ─────────────────────────────────────────────────────────────────\n\ninterface DecrementProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n render?: RenderProp;\n children?: React.ReactNode;\n}\n\nconst Decrement = forwardRef<HTMLButtonElement, DecrementProps>(function NumberFieldDecrement(\n { render, children, ...rest },\n ref\n) {\n const { aria, state } = useNumberFieldContext();\n const el = (\n <button ref={ref} {...aria.decrementButtonProps} {...rest}>\n {children ?? \"−\"}\n </button>\n );\n return renderWith(el, render, state);\n});\n\n// ── HiddenInput ───────────────────────────────────────────────────────────────\n\nconst HiddenInput = function NumberFieldHiddenInput() {\n const { aria } = useNumberFieldContext();\n if (!aria.hiddenInputProps) return null;\n return <input {...aria.hiddenInputProps} />;\n};\n\n// ── ScrubArea ─────────────────────────────────────────────────────────────────\n\nconst ScrubArea = forwardRef<HTMLSpanElement, ScrubAreaProps>(function NumberFieldScrubArea(\n { render, children, direction = \"horizontal\", pixelSensitivity = 4, ...rest },\n ref\n) {\n const { state } = useNumberFieldContext();\n const { scrubAreaProps } = useScrubArea(state, { direction, pixelSensitivity });\n\n const el = (\n <span ref={ref} {...scrubAreaProps} {...(rest as React.HTMLAttributes<HTMLSpanElement>)}>\n {children}\n </span>\n );\n return renderWith(el, render, state);\n});\n\n// ── ScrubAreaCursor ───────────────────────────────────────────────────────────\n//\n// Renders a custom cursor element positioned at the virtual cursor location\n// during pointer lock. Use this to show a drag handle icon while scrubbing.\n// Rendered only when isScrubbing is true.\n\nconst ScrubAreaCursor = forwardRef<HTMLSpanElement, ScrubAreaCursorProps>(\n function NumberFieldScrubAreaCursor({ render, children, style, ...rest }, ref) {\n const { state } = useNumberFieldContext();\n\n if (!state.isScrubbing) return null;\n\n const el = (\n <span\n ref={ref}\n style={{\n position: \"fixed\",\n pointerEvents: \"none\",\n zIndex: 9999,\n ...style,\n }}\n {...(rest as React.HTMLAttributes<HTMLSpanElement>)}\n >\n {children}\n </span>\n );\n return renderWith(el, render, state);\n }\n);\n\n// ── Description ───────────────────────────────────────────────────────────────\n\ninterface DescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {\n children?: React.ReactNode;\n}\n\nconst Description = forwardRef<HTMLParagraphElement, DescriptionProps>(\n function NumberFieldDescription({ children, ...rest }, ref) {\n const { aria } = useNumberFieldContext();\n return (\n <p ref={ref} {...aria.descriptionProps} {...rest}>\n {children}\n </p>\n );\n }\n);\n\n// ── ErrorMessage ──────────────────────────────────────────────────────────────\n\ninterface ErrorMessageProps extends React.HTMLAttributes<HTMLParagraphElement> {\n children?: React.ReactNode;\n}\n\nconst ErrorMessage = forwardRef<HTMLParagraphElement, ErrorMessageProps>(\n function NumberFieldErrorMessage({ children, ...rest }, ref) {\n const { aria, state } = useNumberFieldContext();\n // If no children provided, fall back to the validation error string (if any)\n const content = children ?? state.validationError ?? null;\n if (!content) return null;\n return (\n <p ref={ref} {...aria.errorMessageProps} {...rest}>\n {content}\n </p>\n );\n }\n);\n\n// ── Formatted ─────────────────────────────────────────────────────────────────\n//\n// Read-only display of the current formatted value. Useful for showing the\n// formatted number inline without an editable input (e.g., in a data table).\n\ninterface FormattedProps extends React.HTMLAttributes<HTMLSpanElement> {\n render?: RenderProp;\n}\n\nconst Formatted = forwardRef<HTMLSpanElement, FormattedProps>(function NumberFieldFormatted(\n { render, ...rest },\n ref\n) {\n const { state } = useNumberFieldContext();\n const el = (\n <span ref={ref} aria-hidden=\"true\" {...rest}>\n {state.inputValue}\n </span>\n );\n return renderWith(el, render, state);\n});\n\n// ── Namespace export ──────────────────────────────────────────────────────────\n\nexport const NumberField = {\n Root,\n Label,\n Group,\n Input,\n Increment,\n Decrement,\n HiddenInput,\n ScrubArea,\n ScrubAreaCursor,\n Description,\n ErrorMessage,\n Formatted,\n};\n"]}
|