npm package: @runtypelabs/react-flow
Description: React Flow adapter for building visual flow editors with Runtype
Author: Runtype Labs
Latest version: 0.2.11

# @runtypelabs/react-flow

A React Flow adapter for building visual flow editors with Runtype. This package provides pre-built node components and hooks for creating, editing, and saving flows using the Runtype API.

> Official React Flow adapter published on npm

## Running the Example

From the monorepo root, run:

```bash
pnpm dev:react-flow-example
```

This will build the package and start the example app at http://localhost:3100

## Installation

```bash
pnpm add @runtypelabs/react-flow @xyflow/react
```

## Quick Start

```tsx
import { RuntypeFlowEditor } from '@runtypelabs/react-flow'
import { createClient } from '@runtypelabs/sdk'
import '@xyflow/react/dist/style.css'

const client = createClient({
  apiKey: 'your-api-key',
})

function MyFlowEditor() {
  return (
    <div style={{ width: '100%', height: '600px' }}>
      <RuntypeFlowEditor
        client={client}
        flowId="optional-flow-id"
        onSave={(flow) => console.log('Saved:', flow)}
      />
    </div>
  )
}
```

## Features

- **Pre-built Node Components**: Ready-to-use nodes for prompt, fetch URL, code, conditional, and send email steps
- **API Integration**: Seamlessly load, save, and create flows using `@runtypelabs/sdk`
- **Validation**: Built-in validation for all step types
- **Auto-layout**: Automatic node positioning
- **Fully Typed**: Complete TypeScript support

## Supported Step Types

| Step Type        | Node Component  | Description                             |
| ---------------- | --------------- | --------------------------------------- |
| `prompt`         | PromptNode      | AI text generation with model selection |
| `fetch-url`      | FetchUrlNode    | HTTP requests to fetch data             |
| `transform-data` | CodeNode        | JavaScript code execution               |
| `conditional`    | ConditionalNode | Branch execution based on conditions    |
| `send-email`     | SendEmailNode   | Send emails                             |

## Components

### RuntypeFlowEditor

The main editor component that wraps React Flow with Runtype integration.

```tsx
<RuntypeFlowEditor
  client={runtypeClient}
  flowId="optional-existing-flow-id"
  initialName="My Flow"
  initialDescription="A description"
  initialSteps={[]}
  onSave={(flow) => {...}}
  onChange={(nodes, edges) => {...}}
  onStepSelect={(step) => {...}}
  showToolbar={true}
  readOnly={false}
  className="my-editor"
/>
```

**Props:**

| Prop                 | Type                     | Description                                      |
| -------------------- | ------------------------ | ------------------------------------------------ |
| `client`             | `RuntypeClient`          | Required. Runtype API client instance            |
| `flowId`             | `string`                 | ID of an existing flow to load                   |
| `initialName`        | `string`                 | Initial flow name for new flows                  |
| `initialDescription` | `string`                 | Initial flow description                         |
| `initialSteps`       | `FlowStep[]`             | Initial steps to populate                        |
| `onSave`             | `(flow) => void`         | Callback when flow is saved                      |
| `onChange`           | `(nodes, edges) => void` | Callback when flow changes                       |
| `onStepSelect`       | `(step) => void`         | Callback when a step is selected                 |
| `showToolbar`        | `boolean`                | Whether to show the toolbar (default: true)      |
| `readOnly`           | `boolean`                | Whether the editor is read-only (default: false) |
| `className`          | `string`                 | Custom class name for the container              |

## Hooks

### useRuntypeFlow

Manages flow state and API operations.

```tsx
import { useRuntypeFlow } from '@runtypelabs/react-flow'

function MyCustomEditor() {
  const {
    nodes,
    edges,
    onNodesChange,
    onEdgesChange,
    onConnect,
    flowName,
    setFlowName,
    loadFlow,
    saveFlow,
    createFlow,
    addStep,
    deleteStep,
    updateStep,
    isLoading,
    isSaving,
    error,
    hasUnsavedChanges,
  } = useRuntypeFlow({
    client,
    flowId: 'optional-flow-id',
  })

  // Use with ReactFlow
  return (
    <ReactFlow
      nodes={nodes}
      edges={edges}
      onNodesChange={onNodesChange}
      onEdgesChange={onEdgesChange}
      onConnect={onConnect}
    />
  )
}
```

### useFlowValidation

Validates flow steps and returns errors/warnings.

```tsx
import { useFlowValidation } from '@runtypelabs/react-flow'

function ValidationStatus({ nodes }) {
  const { result, getStepErrors, getStepWarnings } = useFlowValidation({ nodes })

  return (
    <div>
      <p>Valid: {result.isValid ? 'Yes' : 'No'}</p>
      <p>Errors: {result.errors.length}</p>
      <p>Warnings: {result.warnings.length}</p>
    </div>
  )
}
```

## Utilities

### Adapter Functions

Convert between Runtype flow steps and React Flow nodes:

```tsx
import {
  flowStepsToNodes,
  nodesToFlowSteps,
  createEdgesFromNodes,
  createDefaultStep,
} from '@runtypelabs/react-flow'

// Convert Runtype steps to React Flow nodes
const nodes = flowStepsToNodes(steps, {
  onChange: (stepId, updates) => {...},
  onDelete: (stepId) => {...},
})

// Convert back to Runtype steps
const steps = nodesToFlowSteps(nodes)

// Create edges between nodes
const edges = createEdgesFromNodes(nodes)

// Create a new default step
const newStep = createDefaultStep('prompt', 0)
```

### Layout Functions

Auto-layout nodes for better visualization:

```tsx
import { autoLayout, centerNodes, snapToGrid } from '@runtypelabs/react-flow'

// Auto-layout nodes based on edges
const layoutedNodes = autoLayout(nodes, edges, {
  direction: 'vertical',
  startPosition: { x: 400, y: 50 },
})

// Center nodes in viewport
const centeredNodes = centerNodes(nodes, viewportWidth, viewportHeight)

// Snap nodes to grid
const snappedNodes = snapToGrid(nodes, 20)
```

## Custom Node Components

You can use individual node components directly:

```tsx
import {
  PromptNode,
  FetchUrlNode,
  CodeNode,
  ConditionalNode,
  SendEmailNode,
  BaseNode,
} from '@runtypelabs/react-flow'

// Register with ReactFlow
const nodeTypes = {
  prompt: PromptNode,
  'fetch-url': FetchUrlNode,
  'transform-data': CodeNode,
  conditional: ConditionalNode,
  'send-email': SendEmailNode,
}

<ReactFlow nodeTypes={nodeTypes} ... />
```

## TypeScript

Full TypeScript support with exported types:

```tsx
import type {
  FlowStep,
  RuntypeNode,
  RuntypeEdge,
  RuntypeNodeData,
  PromptStepConfig,
  FetchUrlStepConfig,
  TransformDataStepConfig,
  ConditionalStepConfig,
  SendEmailStepConfig,
  FlowValidationResult,
  ValidationError,
  ValidationWarning,
  SavedFlow,
} from '@runtypelabs/react-flow'
```

## Development Notes

### TypeScript

This package exports TypeScript types directly from source files to ensure compatibility across different React versions. TypeScript users will get full type inference automatically.

### Peer Dependencies

This package requires the following peer dependencies:

- `react` ^18.0.0
- `react-dom` ^18.0.0
- `@xyflow/react` ^12.0.0

### Styling

Import React Flow's styles in your application:

```tsx
import '@xyflow/react/dist/style.css'
```

## License

MIT