# Number Input

> Numeric input with stepper buttons, min/max clamping, precision, and locale-aware formatting.

- Package: `@sisyphos-ui/number-input`
- Docs: https://sisyphosui.com/docs/components/number-input
- npm: https://www.npmjs.com/package/@sisyphos-ui/number-input

## Installation

```bash
pnpm add @sisyphos-ui/number-input @sisyphos-ui/core
```

Or use the umbrella package:

```bash
pnpm add @sisyphos-ui/ui
```

## Import

```tsx
import "@sisyphos-ui/number-input/styles.css";
import { NumberInput } from "@sisyphos-ui/number-input";
```

## Examples

### Default

```tsx
import { useState } from "react";
import { NumberInput } from "@sisyphos-ui/ui";

export function Example() {
  const [value, setValue] = useState<number | null>(1);

  return (
    <div className="w-full max-w-[200px]">
      <NumberInput
        label="Quantity"
        min={0}
        max={99}
        step={1}
        value={value}
        onChange={setValue}
      />
    </div>
  );
}
```

### With currency prefix

`prefix` + `precision` format money-shaped values.

```tsx
import { useState } from "react";
import { NumberInput } from "@sisyphos-ui/ui";

export function Example() {
  const [v, setV] = useState<number | null>(299);

  return (
    <NumberInput
      label="Monthly budget"
      prefix="$"
      min={0}
      max={10000}
      step={50}
      precision={2}
      value={v}
      onChange={setV}
    />
  );
}
```

### With suffix

Put units after the value with `suffix`.

```tsx
import { useState } from "react";
import { NumberInput } from "@sisyphos-ui/ui";

export function Example() {
  const [v, setV] = useState<number | null>(30);

  return (
    <NumberInput
      label="Weight"
      suffix="kg"
      min={0}
      max={500}
      step={0.5}
      precision={1}
      value={v}
      onChange={setV}
    />
  );
}
```

### Error state

Track validation yourself and toggle `error` on the control.

```tsx
import { useState } from "react";
import { NumberInput } from "@sisyphos-ui/ui";

export function Example() {
  const [v, setV] = useState<number | null>(0);
  const invalid = v === null || v < 1;

  return (
    <>
      <NumberInput label="Seats" min={1} max={100} value={v} onChange={setV} error={invalid} />
      {invalid && <p>At least 1 seat is required.</p>}
    </>
  );
}
```
