npm package: @hostwebhook/react
Description: Embeddable React components for HostWebhook — event logs, endpoint status, delivery timelines
Latest version: 1.4.1

# @hostwebhook/react

Embeddable React components and hooks for [HostWebhook](https://hostwebhook.com) — webhook monitoring, forms, and event management.

## Install

```sh
npm install @hostwebhook/react
```

## Quick Start

### 1. Provider Setup (for data hooks)

```tsx
import { HostWebhookProvider } from '@hostwebhook/react';
import '@hostwebhook/react/styles.css';

function App() {
  return (
    <HostWebhookProvider apiKey="your_api_key">
      <Dashboard />
    </HostWebhookProvider>
  );
}
```

### 2. Display Events

```tsx
import { WebhookEventLog } from '@hostwebhook/react';

function Dashboard() {
  return <WebhookEventLog endpointId="your_endpoint_id" limit={25} />;
}
```

### 3. Webhook Form (no Provider needed)

```tsx
import { WebhookForm } from '@hostwebhook/react';

<WebhookForm
  endpointToken="whk_abc123"
  fields={[
    { name: 'email', type: 'email', label: 'Email', required: true },
    { name: 'message', type: 'textarea', label: 'Message' },
  ]}
/>
```

## Data Hooks

All data hooks require `<HostWebhookProvider>` and return `{ data, error, loading, refetch }`.

| Hook | Description |
|------|-------------|
| `useEvents(options?)` | Paginated webhook events |
| `useEndpoint(id)` | Single endpoint details |
| `useEndpoints()` | All endpoints |
| `useDeliveries(eventId)` | Delivery attempts for an event |

```tsx
import { useEvents } from '@hostwebhook/react';

function FailedEvents() {
  const { data, loading } = useEvents({ status: 'failed', limit: 10 });
  if (loading) return <p>Loading...</p>;
  return <ul>{data?.events.map(e => <li key={e.id}>{e.eventType}</li>)}</ul>;
}
```

## Form System

Forms submit data directly to `POST /api/in/:token` (public webhook ingress). Three usage modes:

### Quick Mode

Auto-generates fields from a `fields` array:

```tsx
<WebhookForm
  endpointToken="whk_abc123"
  fields={[
    { name: 'name', label: 'Name', required: true },
    { name: 'email', type: 'email', label: 'Email', required: true },
    { name: 'plan', type: 'select', label: 'Plan', options: [
      { label: 'Free', value: 'free' },
      { label: 'Pro', value: 'pro' },
    ]},
  ]}
  onSuccess={(result) => alert(`Created event: ${result.eventId}`)}
/>
```

### Composable Mode

Use `<WebhookField>` and `<WebhookSubmit>` sub-components:

```tsx
<WebhookForm endpointToken="whk_abc123">
  <WebhookField name="email" type="email" label="Email" required />
  <WebhookField name="message" type="textarea" label="Message" />
  <WebhookSubmit>Send Feedback</WebhookSubmit>
</WebhookForm>
```

### Headless Mode

Full render control via render prop:

```tsx
<WebhookForm endpointToken="whk_abc123">
  {(form) => (
    <div>
      <input {...form.getFieldProps('email')} placeholder="Email" />
      {form.getFieldMeta('email').error && (
        <span>{form.getFieldMeta('email').error}</span>
      )}
      <button type="submit" disabled={form.isSubmitting}>Submit</button>
    </div>
  )}
</WebhookForm>
```

### Hook-only

Use `useWebhookForm()` directly without the `<WebhookForm>` wrapper:

```tsx
import { useWebhookForm } from '@hostwebhook/react';

function MyForm() {
  const { values, handleChange, handleSubmit, isSubmitting } = useWebhookForm({
    endpointToken: 'whk_abc123',
    initialValues: { email: '' },
    onSuccess: (result) => console.log(result.eventId),
  });

  return (
    <form onSubmit={handleSubmit}>
      <input name="email" value={values.email} onChange={handleChange} />
      <button type="submit" disabled={isSubmitting}>Send</button>
    </form>
  );
}
```

## Display Components

### WebhookEventLog

Paginated table of webhook events with status filters.

```tsx
<WebhookEventLog
  endpointId="..."
  limit={25}
  pollInterval={5000}
  showFilters
  onEventClick={(event) => console.log(event)}
/>
```

### EndpointStatus

Health status indicator with optional details.

```tsx
<EndpointStatus endpointId="..." showDetails />
```

### DeliveryTimeline

Vertical timeline showing all delivery attempts for an event.

```tsx
<DeliveryTimeline eventId="..." />
```

## Validation

Built-in validators: `required`, `email`, `url`, `minLength`, `maxLength`, `min`, `max`, `pattern`.

Custom field validation:

```tsx
<WebhookField
  name="age"
  type="number"
  validate={(value) => Number(value) < 18 ? 'Must be 18+' : undefined}
/>
```

Form-level validation:

```tsx
<WebhookForm
  endpointToken="whk_abc123"
  validate={(values) => {
    const errors: Record<string, string> = {};
    if (!values.email && !values.phone) errors.email = 'Email or phone required';
    return errors;
  }}
>
```

## Styling

Import the default stylesheet:

```tsx
import '@hostwebhook/react/styles.css';
```

All CSS classes use the `hwk-` prefix. Customize the theme via CSS custom properties:

```css
:root {
  --hwk-color-bg: #1a1a2e;
  --hwk-color-text: #e0e0e0;
  --hwk-color-border: #333;
  --hwk-color-info: #4fc3f7;
  --hwk-radius: 8px;
  --hwk-font-family: 'Inter', sans-serif;
}
```

## Security

The form system includes built-in protections:

- **Honeypot** anti-bot field (enabled by default)
- **Submit cooldown** prevents rapid-fire spam (2s default)
- **XSS sanitization** strips `<script>` tags and `on*=` handlers
- **Payload size limit** rejects payloads over 1MB

## License

MIT