# `` _(no submodules)_ ## Purpose Locale-aware numeric input. Parses incoming text using the active locale's decimal and grouping separators, accepts locale-specific digit glyphs (`٣٫١٤` in Arabic-Indic), and emits a canonical `number | null` through `onValueChange`. Switches to a raw editable buffer on focus to avoid cursor jumps caused by re-formatting mid-keystroke; renders the locale-formatted value on blur. The plain `` is unaffected — `` is a sibling primitive consumers opt into per call site, so existing form code is not disturbed. ## Features - Per-locale separator detection via `Intl.NumberFormat.formatToParts(12345.6)` — handles en-GB `1,234.5`, de-DE `1.234,5`, fr-FR `1 234,5`, ar-AE Arabic-Indic glyphs. - Digit-folding for non-Latin numbering systems — Eastern Arabic, Devanagari, Bengali, etc. - Focus / blur buffer split — raw Latin during edit, locale formatted at rest. - Empty input emits `null` (not `0` or `NaN`). - Invalid input on blur reverts to the previously valid formatted value rather than corrupting state. - Controlled OR uncontrolled — pass `value` (controlled) or `defaultValue` (uncontrolled). - `displayOptions: Intl.NumberFormatOptions` lets the rest-state format render percent, currency, scientific, etc. ## Usage: Basic Example ```tsx import { InputNumber } from "@suaveplan/react-ui"; const [amount, setAmount] = useState(null); ``` ## Usage: Advanced Example Currency-style display (rest-state shows `1,234.50` while focused buffer shows `1234.5`): ```tsx ``` Bind directly to a form library's controlled value, with locale override for a multi-currency entry form: ```tsx ``` ## API Reference ### `` - `value?: number | null` — controlled. `null` renders empty. - `defaultValue?: number | null` — uncontrolled initial. - `onValueChange?: (value: number | null) => void` — fires on blur. - `locale?: string` — defaults to `useReactUiLocale().locale`. - `displayOptions?: Intl.NumberFormatOptions`. - All other `` HTML attributes are forwarded EXCEPT `value`, `defaultValue`, `onChange`, `type` (the component owns those). ### `parseLocaleNumber(text, locale): number | null` Standalone utility for parsing a locale-formatted numeric string. Used internally by the component; exported for consumers needing the same parse logic outside the component. ## Implementation Notes - The `Intl.NumberFormat` instance is cached per `(locale, displayOptions)` via `useMemo`. The separator probe (`formatToParts(12345.6)`) is also cached per locale at module level. - `onValueChange` fires only on blur to avoid emitting `null` for every transient unparseable keystroke. Forms that need keystroke-level validation can subscribe to `onChange` on the underlying `` directly via the spread (we do not own `onChange` once the user has supplied one). - The component uses `type="text"` with `inputMode="decimal"` rather than `type="number"`. `type="number"` rejects locale-specific separators in Chrome and triggers spinner UI consumers usually do not want. - When a parent re-renders with an externally-changed `value` while the input is NOT focused, the displayed value re-formats. While focused, the focused-buffer text wins so the user is not interrupted mid-edit.