Skip to content

Getting Started

Terminal window
npm install raqam

Peer dependencies: React 18 or 19.

Integer field with min 0 and steppers.

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>
);
}
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>
);
}

Like all React form controls, raqam supports both patterns.

<NumberField.Root locale="en-US" defaultValue={42}>
<NumberField.Input />
</NumberField.Root>
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 }.

<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.

<NumberField.Root
locale="en-US"
defaultValue={50}
minValue={0}
maxValue={100}
step={5}
largeStep={25}
>
<NumberField.Input />
</NumberField.Root>
KeyAction
↑ / ↓step (default: 1)
Shift + ↑/↓largeStep (default: 10)
Ctrl/Cmd + ↑/↓smallStep (default: 0.1)
Page Up/DownlargeStep
Home / Endjump to minValue / maxValue

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.

raqam is written in TypeScript. Key types:

import type {
UseNumberFieldStateOptions,
NumberFieldState,
UseNumberFieldProps,
NumberFieldAria,
ChangeReason,
} from "raqam";