npm package: @formwire/react
Description: React components and hooks for FormWire
Author: FormWire Team
Latest version: 1.0.0

# @formwire/react

React components and hooks for FormWire - Ultra-lightweight form state management.

## Features

- **React Hooks** - Modern React patterns
- **High Performance** - Optimized with selective subscriptions and memoization
- **TypeScript Ready** - Full type support
- **Zero Dependencies** - No external dependencies (except React)
- **Memory Efficient** - Automatic cleanup with WeakMap

## Installation

```bash
npm install @formwire/react
```

## Quick Start

```jsx
import { Form, Field } from '@formwire/react';

function MyForm() {
  return (
    <Form onSubmit={(values) => console.log(values)}>
      <Field
        name="email"
        validate={(value) => {
          if (!value) return 'Email is required';
          if (!value.includes('@')) return 'Invalid email';
          return undefined;
        }}
      >
        {({ input, meta }) => (
          <div>
            <input {...input} placeholder="Email" />
            {meta.error && <span style={{ color: 'red' }}>{meta.error}</span>}
          </div>
        )}
      </Field>
      
      <button type="submit">Submit</button>
    </Form>
  );
}
```

## Components

### Form

Root form component with context provider.

```jsx
<Form
  onSubmit={(values) => void}
  initialValues={object}
  defaultValidateOn="blur" | "change"
  engine={FormEngine}
>
  {children}
</Form>
```

**Props:**
- `onSubmit` (function): Submit handler
- `initialValues` (object): Initial form values
- `defaultValidateOn` (string): Default validation mode ('blur' or 'change')
- `engine` (FormEngine): External engine instance (optional)

### Field

High-performance field component with optimized subscriptions and validation.

```jsx
<Field
  name="fieldName"
  validate={(value, allValues) => string | undefined}
  validateOn="blur" | "change"
  debounceDelay={number}
  subscription={object}
>
  {({ input, meta }) => JSX}
</Field>
```

**Props:**
- `name` (string): Field name
- `validate` (function): Validator function
- `validateOn` (string): Validation mode ('blur' or 'change')
- `debounceDelay` (number): Debouncing delay in milliseconds
- `subscription` (object): Selective subscriptions

**Render Props:**
- `input`: Field input props (`{ name, value, onChange, onBlur, onFocus }`)
- `meta`: Field metadata (`{ error, touched, active, dirty }`)

### FieldArray

Component for working with field arrays.

```jsx
<FieldArray name="items">
  {({ fields, push, pop, remove, move, insert }) => (
    <div>
      {fields.map((field, index) => (
        <div key={field.__id}>
          <Field name={`${field.name}.title`}>
            {({ input }) => <input {...input} />}
          </Field>
          <button onClick={() => remove(index)}>Remove</button>
        </div>
      ))}
      <button onClick={() => push({ title: '' })}>Add Item</button>
    </div>
  )}
</FieldArray>
```

**Props:**
- `name` (string): Array field name

**Render Props:**
- `fields`: Array of field objects with stable IDs
- `push`: Add item to end
- `pop`: Remove last item
- `remove`: Remove item by index
- `move`: Move item from one index to another
- `insert`: Insert item at specific index

## Hooks

### useField

Hook for managing field state.

```jsx
function MyField({ name }) {
  const { value, onChange, onBlur, error, touched } = useField(name, {
    validate: (value) => !value ? 'Required' : undefined,
    validateOn: 'blur'
  });

  return (
    <div>
      <input
        value={value}
        onChange={onChange}
        onBlur={onBlur}
      />
      {touched && error && <span>{error}</span>}
    </div>
  );
}
```

**Parameters:**
- `name` (string): Field name
- `options` (object): Field options
  - `validate` (function): Validator function
  - `validateOn` (string): Validation mode
  - `debounceDelay` (number): Debouncing delay
  - `subscription` (object): Selective subscriptions

**Returns:**
- `value`: Field value
- `onChange`: Change handler
- `onBlur`: Blur handler
- `onFocus`: Focus handler
- `error`: Validation error
- `touched`: Touched status
- `active`: Active status
- `input`: Input props object
- `meta`: Metadata object

### useFormState

Hook for subscribing to form state.

```jsx
function FormStatus() {
  const { values, errors, submitting, valid } = useFormState({
    values: true,
    errors: true,
    submitting: true
  });

  return (
    <div>
      <p>Valid: {valid ? 'Yes' : 'No'}</p>
      <p>Submitting: {submitting ? 'Yes' : 'No'}</p>
      <p>Values: {JSON.stringify(values)}</p>
    </div>
  );
}
```

**Parameters:**
- `subscription` (object): Selective subscriptions
  - `values` (boolean): Subscribe to values
  - `errors` (boolean): Subscribe to errors
  - `touched` (boolean): Subscribe to touched
  - `active` (boolean): Subscribe to active
  - `submitting` (boolean): Subscribe to submitting

**Returns:**
- `values`: Form values
- `errors`: Validation errors
- `touched`: Touched fields
- `active`: Active field
- `submitting`: Submission status
- `valid`: Form validity
- `dirty`: Dirty status
- `pristine`: Pristine status

### useWatch

Hook for watching specific field.

```jsx
function EmailWatcher() {
  const email = useWatch('email', (value) => value?.toLowerCase());

  return <p>Email: {email}</p>;
}
```

**Parameters:**
- `name` (string): Field name
- `selector` (function): Selector for transformation

**Returns:**
- Field value (transformed by selector)

### useFormSubmit

Hook for handling form submission.

```jsx
function SubmitButton() {
  const { handleSubmit, submitting } = useFormSubmit(async (values) => {
    await submitToAPI(values);
  });

  return (
    <button onClick={handleSubmit} disabled={submitting}>
      {submitting ? 'Submitting...' : 'Submit'}
    </button>
  );
}
```

**Parameters:**
- `onSubmit` (function): Submit handler

**Returns:**
- `handleSubmit`: Submit handler
- `submitting`: Submission status

## Context

### FormProvider

Context provider for form engine.

```jsx
import { FormProvider } from '@formwire/react';

function App() {
  return (
    <FormProvider engine={customEngine}>
      <MyForm />
    </FormProvider>
  );
}
```

### useFormEngine

Hook for accessing form engine.

```jsx
function CustomComponent() {
  const engine = useFormEngine();
  
  // Use engine directly
  engine.set('customField', 'value');
}
```

### useFormContext

Hook for accessing form context.

```jsx
function CustomComponent() {
  const context = useFormContext();
  
  // Access context properties
  console.log(context.engine);
}
```

## Advanced Usage

### Custom Field Component

```jsx
function CustomField({ name, label, ...props }) {
  return (
    <Field name={name} {...props}>
      {({ input, meta }) => (
        <div className="field">
          <label>{label}</label>
          <input {...input} className={meta.error ? 'error' : ''} />
          {meta.touched && meta.error && (
            <div className="error-message">{meta.error}</div>
          )}
        </div>
      )}
    </Field>
  );
}
```

### Selective Subscriptions

```jsx
function OptimizedField({ name }) {
  const { value, onChange } = useField(name, {
    subscription: {
      value: true,
      onChange: true
      // Don't subscribe to error, touched, etc.
    }
  });

  return <input value={value} onChange={onChange} />;
}
```

### Custom Validation

```jsx
function EmailField() {
  return (
    <Field
      name="email"
      validate={async (value) => {
        if (!value) return 'Email is required';
        if (!value.includes('@')) return 'Invalid email format';
        
        // Async validation
        const exists = await checkEmailExists(value);
        if (exists) return 'Email already exists';
        
        return undefined;
      }}
    >
      {({ input, meta }) => (
        <div>
          <input {...input} type="email" />
          {meta.error && <span>{meta.error}</span>}
        </div>
      )}
    </Field>
  );
}
```

## Performance Tips

1. **Use selective subscriptions** to minimize re-renders
2. **Memoize expensive computations** with useMemo
3. **Use debounced validation** for better performance
4. **Avoid unnecessary subscriptions** in useFormState

## License

MIT