@runtypelabs/react-flow 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,289 @@
1
+ # @runtypelabs/react-flow
2
+
3
+ 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.
4
+
5
+ ## Running the Example
6
+
7
+ From the monorepo root, run:
8
+
9
+ ```bash
10
+ pnpm dev:react-flow-example
11
+ ```
12
+
13
+ This will build the package and start the example app at http://localhost:3100
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pnpm add @runtypelabs/react-flow @xyflow/react
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ```tsx
24
+ import { RuntypeFlowEditor } from '@runtypelabs/react-flow'
25
+ import { createClient } from '@runtypelabs/sdk'
26
+ import '@xyflow/react/dist/style.css'
27
+
28
+ const client = createClient({
29
+ apiKey: 'your-api-key',
30
+ })
31
+
32
+ function MyFlowEditor() {
33
+ return (
34
+ <div style={{ width: '100%', height: '600px' }}>
35
+ <RuntypeFlowEditor
36
+ client={client}
37
+ flowId="optional-flow-id"
38
+ onSave={(flow) => console.log('Saved:', flow)}
39
+ />
40
+ </div>
41
+ )
42
+ }
43
+ ```
44
+
45
+ ## Features
46
+
47
+ - **Pre-built Node Components**: Ready-to-use nodes for prompt, fetch URL, code, conditional, and send email steps
48
+ - **API Integration**: Seamlessly load, save, and create flows using `@runtypelabs/sdk`
49
+ - **Validation**: Built-in validation for all step types
50
+ - **Auto-layout**: Automatic node positioning
51
+ - **Fully Typed**: Complete TypeScript support
52
+
53
+ ## Supported Step Types
54
+
55
+ | Step Type | Node Component | Description |
56
+ |-----------|---------------|-------------|
57
+ | `prompt` | PromptNode | AI text generation with model selection |
58
+ | `fetch-url` | FetchUrlNode | HTTP requests to fetch data |
59
+ | `transform-data` | CodeNode | JavaScript code execution |
60
+ | `conditional` | ConditionalNode | Branch execution based on conditions |
61
+ | `send-email` | SendEmailNode | Send emails |
62
+
63
+ ## Components
64
+
65
+ ### RuntypeFlowEditor
66
+
67
+ The main editor component that wraps React Flow with Runtype integration.
68
+
69
+ ```tsx
70
+ <RuntypeFlowEditor
71
+ client={runtypeClient}
72
+ flowId="optional-existing-flow-id"
73
+ initialName="My Flow"
74
+ initialDescription="A description"
75
+ initialSteps={[]}
76
+ onSave={(flow) => {...}}
77
+ onChange={(nodes, edges) => {...}}
78
+ onStepSelect={(step) => {...}}
79
+ showToolbar={true}
80
+ readOnly={false}
81
+ className="my-editor"
82
+ />
83
+ ```
84
+
85
+ **Props:**
86
+
87
+ | Prop | Type | Description |
88
+ |------|------|-------------|
89
+ | `client` | `RuntypeClient` | Required. Runtype API client instance |
90
+ | `flowId` | `string` | ID of an existing flow to load |
91
+ | `initialName` | `string` | Initial flow name for new flows |
92
+ | `initialDescription` | `string` | Initial flow description |
93
+ | `initialSteps` | `FlowStep[]` | Initial steps to populate |
94
+ | `onSave` | `(flow) => void` | Callback when flow is saved |
95
+ | `onChange` | `(nodes, edges) => void` | Callback when flow changes |
96
+ | `onStepSelect` | `(step) => void` | Callback when a step is selected |
97
+ | `showToolbar` | `boolean` | Whether to show the toolbar (default: true) |
98
+ | `readOnly` | `boolean` | Whether the editor is read-only (default: false) |
99
+ | `className` | `string` | Custom class name for the container |
100
+
101
+ ## Hooks
102
+
103
+ ### useRuntypeFlow
104
+
105
+ Manages flow state and API operations.
106
+
107
+ ```tsx
108
+ import { useRuntypeFlow } from '@runtypelabs/react-flow'
109
+
110
+ function MyCustomEditor() {
111
+ const {
112
+ nodes,
113
+ edges,
114
+ onNodesChange,
115
+ onEdgesChange,
116
+ onConnect,
117
+ flowName,
118
+ setFlowName,
119
+ loadFlow,
120
+ saveFlow,
121
+ createFlow,
122
+ addStep,
123
+ deleteStep,
124
+ updateStep,
125
+ isLoading,
126
+ isSaving,
127
+ error,
128
+ hasUnsavedChanges,
129
+ } = useRuntypeFlow({
130
+ client,
131
+ flowId: 'optional-flow-id',
132
+ })
133
+
134
+ // Use with ReactFlow
135
+ return (
136
+ <ReactFlow
137
+ nodes={nodes}
138
+ edges={edges}
139
+ onNodesChange={onNodesChange}
140
+ onEdgesChange={onEdgesChange}
141
+ onConnect={onConnect}
142
+ />
143
+ )
144
+ }
145
+ ```
146
+
147
+ ### useFlowValidation
148
+
149
+ Validates flow steps and returns errors/warnings.
150
+
151
+ ```tsx
152
+ import { useFlowValidation } from '@runtypelabs/react-flow'
153
+
154
+ function ValidationStatus({ nodes }) {
155
+ const { result, getStepErrors, getStepWarnings } = useFlowValidation({ nodes })
156
+
157
+ return (
158
+ <div>
159
+ <p>Valid: {result.isValid ? 'Yes' : 'No'}</p>
160
+ <p>Errors: {result.errors.length}</p>
161
+ <p>Warnings: {result.warnings.length}</p>
162
+ </div>
163
+ )
164
+ }
165
+ ```
166
+
167
+ ## Utilities
168
+
169
+ ### Adapter Functions
170
+
171
+ Convert between Runtype flow steps and React Flow nodes:
172
+
173
+ ```tsx
174
+ import {
175
+ flowStepsToNodes,
176
+ nodesToFlowSteps,
177
+ createEdgesFromNodes,
178
+ createDefaultStep,
179
+ } from '@runtypelabs/react-flow'
180
+
181
+ // Convert Runtype steps to React Flow nodes
182
+ const nodes = flowStepsToNodes(steps, {
183
+ onChange: (stepId, updates) => {...},
184
+ onDelete: (stepId) => {...},
185
+ })
186
+
187
+ // Convert back to Runtype steps
188
+ const steps = nodesToFlowSteps(nodes)
189
+
190
+ // Create edges between nodes
191
+ const edges = createEdgesFromNodes(nodes)
192
+
193
+ // Create a new default step
194
+ const newStep = createDefaultStep('prompt', 0)
195
+ ```
196
+
197
+ ### Layout Functions
198
+
199
+ Auto-layout nodes for better visualization:
200
+
201
+ ```tsx
202
+ import { autoLayout, centerNodes, snapToGrid } from '@runtypelabs/react-flow'
203
+
204
+ // Auto-layout nodes based on edges
205
+ const layoutedNodes = autoLayout(nodes, edges, {
206
+ direction: 'vertical',
207
+ startPosition: { x: 400, y: 50 },
208
+ })
209
+
210
+ // Center nodes in viewport
211
+ const centeredNodes = centerNodes(nodes, viewportWidth, viewportHeight)
212
+
213
+ // Snap nodes to grid
214
+ const snappedNodes = snapToGrid(nodes, 20)
215
+ ```
216
+
217
+ ## Custom Node Components
218
+
219
+ You can use individual node components directly:
220
+
221
+ ```tsx
222
+ import {
223
+ PromptNode,
224
+ FetchUrlNode,
225
+ CodeNode,
226
+ ConditionalNode,
227
+ SendEmailNode,
228
+ BaseNode,
229
+ } from '@runtypelabs/react-flow'
230
+
231
+ // Register with ReactFlow
232
+ const nodeTypes = {
233
+ prompt: PromptNode,
234
+ 'fetch-url': FetchUrlNode,
235
+ 'transform-data': CodeNode,
236
+ conditional: ConditionalNode,
237
+ 'send-email': SendEmailNode,
238
+ }
239
+
240
+ <ReactFlow nodeTypes={nodeTypes} ... />
241
+ ```
242
+
243
+ ## TypeScript
244
+
245
+ Full TypeScript support with exported types:
246
+
247
+ ```tsx
248
+ import type {
249
+ FlowStep,
250
+ RuntypeNode,
251
+ RuntypeEdge,
252
+ RuntypeNodeData,
253
+ PromptStepConfig,
254
+ FetchUrlStepConfig,
255
+ TransformDataStepConfig,
256
+ ConditionalStepConfig,
257
+ SendEmailStepConfig,
258
+ FlowValidationResult,
259
+ ValidationError,
260
+ ValidationWarning,
261
+ SavedFlow,
262
+ } from '@runtypelabs/react-flow'
263
+ ```
264
+
265
+ ## Development Notes
266
+
267
+ ### TypeScript
268
+
269
+ This package exports TypeScript types directly from source files to ensure compatibility across different React versions. TypeScript users will get full type inference automatically.
270
+
271
+ ### Peer Dependencies
272
+
273
+ This package requires the following peer dependencies:
274
+ - `react` ^18.0.0
275
+ - `react-dom` ^18.0.0
276
+ - `@xyflow/react` ^12.0.0
277
+
278
+ ### Styling
279
+
280
+ Import React Flow's styles in your application:
281
+
282
+ ```tsx
283
+ import '@xyflow/react/dist/style.css'
284
+ ```
285
+
286
+ ## License
287
+
288
+ MIT
289
+
@@ -0,0 +1,3 @@
1
+ # Travrse API Configuration
2
+ VITE_TRAVRSE_API_URL=http://localhost:8787/v1
3
+ VITE_TRAVRSE_API_KEY=your_api_key_here
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Runtype React Flow Example</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+ html, body, #root {
14
+ width: 100%;
15
+ height: 100%;
16
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
17
+ }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <div id="root"></div>
22
+ <script type="module" src="/src/main.tsx"></script>
23
+ </body>
24
+ </html>
25
+
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/exedev/GitHub/core/node_modules/.pnpm/browserslist@4.28.1/node_modules/browserslist/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/browserslist@4.28.1/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/exedev/GitHub/core/node_modules/.pnpm/browserslist@4.28.1/node_modules/browserslist/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/browserslist@4.28.1/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../../node_modules/.pnpm/browserslist@4.28.1/node_modules/browserslist/cli.js" "$@"
19
+ else
20
+ exec node "$basedir/../../../../../node_modules/.pnpm/browserslist@4.28.1/node_modules/browserslist/cli.js" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/exedev/GitHub/core/node_modules/.pnpm/terser@5.44.1/node_modules/terser/bin/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/terser@5.44.1/node_modules/terser/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/terser@5.44.1/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/exedev/GitHub/core/node_modules/.pnpm/terser@5.44.1/node_modules/terser/bin/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/terser@5.44.1/node_modules/terser/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/terser@5.44.1/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../../node_modules/.pnpm/terser@5.44.1/node_modules/terser/bin/terser" "$@"
19
+ else
20
+ exec node "$basedir/../../../../../node_modules/.pnpm/terser@5.44.1/node_modules/terser/bin/terser" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
19
+ else
20
+ exec node "$basedir/../typescript/bin/tsc" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
19
+ else
20
+ exec node "$basedir/../typescript/bin/tsserver" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/exedev/GitHub/core/node_modules/.pnpm/vite@5.4.21_@types+node@25.0.3_lightningcss@1.30.1_terser@5.44.1/node_modules/vite/bin/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/vite@5.4.21_@types+node@25.0.3_lightningcss@1.30.1_terser@5.44.1/node_modules/vite/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/vite@5.4.21_@types+node@25.0.3_lightningcss@1.30.1_terser@5.44.1/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/exedev/GitHub/core/node_modules/.pnpm/vite@5.4.21_@types+node@25.0.3_lightningcss@1.30.1_terser@5.44.1/node_modules/vite/bin/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/vite@5.4.21_@types+node@25.0.3_lightningcss@1.30.1_terser@5.44.1/node_modules/vite/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/vite@5.4.21_@types+node@25.0.3_lightningcss@1.30.1_terser@5.44.1/node_modules:/home/exedev/GitHub/core/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../vite/bin/vite.js" "$@"
19
+ else
20
+ exec node "$basedir/../vite/bin/vite.js" "$@"
21
+ fi
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@runtypelabs/react-flow-example",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "@runtypelabs/sdk": "workspace:*",
13
+ "@runtypelabs/react-flow": "workspace:*",
14
+ "@xyflow/react": "^12.0.0",
15
+ "react": "^18.3.1",
16
+ "react-dom": "^18.3.1"
17
+ },
18
+ "devDependencies": {
19
+ "@types/react": "^18.3.0",
20
+ "@types/react-dom": "^18.3.0",
21
+ "@vitejs/plugin-react": "^4.2.0",
22
+ "typescript": "^5.3.3",
23
+ "vite": "^5.0.0"
24
+ }
25
+ }
26
+