# NumberField

A controlled input component designed for numeric values, providing parsing, validation, and seamless integration with form libraries like React Final Form. **NumberField** ensures that user input is always treated as a numeric value (or empty string) while maintaining compatibility with browser-native number input validation.

## Features

- **Controlled/Uncontrolled Support:** Works as a controlled component (via `value`) or within form libraries (via `input`).
- **Automatic Parsing:** Converts user input to a numeric value (float) or empty string.
- **Form Integration:** Compatible with React Final Form's `Field` component.
- **Dual Input Handling:** Uses a visible `TextField` for user interaction and a hidden input for form state management.
- **Validation:** Leverages HTML5 `type="number"` validation with fallback to numeric parsing.

## Basic Usage

### Standalone (Controlled)

```jsx
import { useState } from 'react';
import { NumberField } from '@k-int/stripes-kint-components';

const AgeInput = () => {
  const [age, setAge] = useState('');

  return (
    <NumberField
      label="Enter your age"
      value={age}
      onChange={(e, value) => setAge(value)}
      aria-label="Age input"
    />
  );
};

export default AgeInput;
```

### With React Final Form

```jsx
import { Field } from 'react-final-form';
import { NumberField } from '@k-int/stripes-kint-components';

const FormAgeField = () => (
  <Field
    name="age"
    render={({ input }) => (
      <NumberField
        label="Age"
        input={input}
        aria-label="Form age input"
      />
    )}
  />
);

export default FormAgeField;
```

## Props

| Prop        | Type       | Required | Description                                                                                                  |
|-------------|------------|----------|--------------------------------------------------------------------------------------------------------------|
| `input`     | `object`   | ✕        | Form library input object (e.g., from React Final Form). Must contain `name`, `onChange`, and `value`.       |
| `value`     | `number`   | ✕        | Controlled value (use either `input` or `value`, not both).                                                 |
| `onChange`  | `function` | ✕        | Custom change handler: `(event: React.ChangeEvent, value: number | '') => void`.                               |
| `onBlur`    | `function` | ✕        | Custom blur handler: `(event: React.FocusEvent) => void`.                                                   |
| ...TextFieldProps | `any`     | ✕        | All other props passed to underlying [TextField](https://stripes.github.io/stripes-components/TextField).   |

## Behavior Details

### Input Handling
- **User Input:** Directly manipulates a visible `TextField`
- **Value Parsing:**
  ```js
  const parsedValue = parseFloat(userInput);
  // Returns number or NaN
  ```
- **Form State:** Maintains a hidden `<input>` that always contains:
    - Valid number (as float)
    - Empty string (for invalid/empty input)

### Value Propagation
1. User types "12.5" ➔ `handleUserChange`:
   ```js
   parsedValue = 12.5
   setNumValue(12.5)      // Updates visible field
   changeField(12.5)     // Updates hidden input
   ```
2. Hidden input's `onChange`:
   ```js
   input.onChange(12.5)  // Propagates to form library
   passedOnChange(12.5)  // Notifies custom handler
   ```

## Integration Notes

### Form Library Requirements
When using with React Final Form:
```jsx
<Field
  name="quantity"
  parse={v => v === '' ? undefined : Number(v)}  // Convert empty string to undefined
  render={({ input }) => (
    <NumberField
      input={input}
      label="Quantity"
    />
  )}
/>
```

### Styling/Validation
- Inherits all styling capabilities from `@folio/stripes-components/TextField`
- Browser-native number validation shown via:
  ```jsx
  <NumberField
    type="number"
    min={0}
    max={100}
    step={0.1}
  />
  ```

## Error Handling
Implement custom error states through form library integrations or wrapper components:
```jsx
const ErrorProneField = ({ meta, ...props }) => (
  <NumberField
    {...props}
    error={meta.touched && meta.error}
    aria-label="Error-prone field"
  />
);
```