Getting Started
Installation
Section titled “Installation”npm install raqampnpm add raqamyarn add raqamPeer dependencies: React 18 or 19.
Your first field
Section titled “Your first field”Integer field with min 0 and steppers.
Component API (recommended)
Section titled “Component API (recommended)”import { NumberField } from "raqam";
export function QuantityInput() { return ( <NumberField.Root locale="en-US" defaultValue={1} minValue={0}> <NumberField.Label>Quantity</NumberField.Label> <NumberField.Group> <NumberField.Decrement>−</NumberField.Decrement> <NumberField.Input /> <NumberField.Increment>+</NumberField.Increment> </NumberField.Group> </NumberField.Root> );}Hook API (maximum control)
Section titled “Hook API (maximum control)”import { useRef } from "react";import { useNumberFieldState, useNumberField } from "raqam";
export function QuantityInput() { const inputRef = useRef<HTMLInputElement>(null);
const state = useNumberFieldState({ locale: "en-US", defaultValue: 1, minValue: 0, });
const { labelProps, groupProps, inputProps, incrementButtonProps, decrementButtonProps } = useNumberField({ locale: "en-US", minValue: 0 }, state, inputRef);
return ( <div> <label {...labelProps}>Quantity</label> <div {...groupProps}> <button {...decrementButtonProps}>−</button> <input {...inputProps} ref={inputRef} /> <button {...incrementButtonProps}>+</button> </div> </div> );}Controlled vs uncontrolled
Section titled “Controlled vs uncontrolled”Like all React form controls, raqam supports both patterns.
Uncontrolled (defaultValue)
Section titled “Uncontrolled (defaultValue)”<NumberField.Root locale="en-US" defaultValue={42}> <NumberField.Input /></NumberField.Root>Controlled (value + onChange)
Section titled “Controlled (value + onChange)”const [value, setValue] = useState<number | null>(42);
<NumberField.Root locale="en-US" value={value} onChange={setValue}> <NumberField.Input /></NumberField.Root>onChange receives number | null whenever the parsed numeric value changes.
If you need metadata about how the change happened, use onValueChange on
NumberField.Root for { reason, formattedValue }.
Currency formatting
Section titled “Currency formatting”<NumberField.Root locale="en-US" formatOptions={{ style: "currency", currency: "USD" }} defaultValue={0} minValue={0}> <NumberField.Label>Price</NumberField.Label> <NumberField.Group> <NumberField.Decrement>−</NumberField.Decrement> <NumberField.Input /> <NumberField.Increment>+</NumberField.Increment> </NumberField.Group></NumberField.Root>The formatOptions prop accepts any Intl.NumberFormatOptions. Use
presets for common configurations.
Adding min/max/step
Section titled “Adding min/max/step”<NumberField.Root locale="en-US" defaultValue={50} minValue={0} maxValue={100} step={5} largeStep={25}> <NumberField.Input /></NumberField.Root>| Key | Action |
|---|---|
| ↑ / ↓ | step (default: 1) |
| Shift + ↑/↓ | largeStep (default: 10) |
| Ctrl/Cmd + ↑/↓ | smallStep (default: 0.1) |
| Page Up/Down | largeStep |
| Home / End | jump to minValue / maxValue |
Form integration
Section titled “Form integration”Use NumberField.HiddenInput to submit the raw numeric value in an HTML form.
<form method="post" action="/api/price"> <NumberField.Root locale="en-US" name="price" defaultValue={9.99}> <NumberField.Label>Price</NumberField.Label> <NumberField.Input /> <NumberField.HiddenInput /> </NumberField.Root> <button type="submit">Save</button></form>For library-managed forms see react-hook-form and Formik recipes.
TypeScript
Section titled “TypeScript”raqam is written in TypeScript. Key types:
import type { UseNumberFieldStateOptions, NumberFieldState, UseNumberFieldProps, NumberFieldAria, ChangeReason,} from "raqam";