@dschz/solid-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 +332 -0
- package/dist/index/index.d.ts +1582 -0
- package/dist/index/index.js +3 -0
- package/dist/index/index.jsx +207 -0
- package/dist/styles/index.css +1 -0
- package/dist/styles/index.d.ts +2 -0
- package/package.json +111 -0
package/README.md
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://assets.solidjs.com/banner?project=solid-flow&type=Ecosystem&background=tiles" alt="@dschz/solid-flow banner" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# @dschz/solid-flow
|
|
6
|
+
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://www.npmjs.com/package/@dschz/solid-flow)
|
|
9
|
+
[](https://bundlephobia.com/package/@dschz/solid-flow)
|
|
10
|
+
[](https://github.com/dsnchz/solid-flow/actions/workflows/ci.yaml)
|
|
11
|
+
|
|
12
|
+
> Solid Flow is a port of [React Flow](https://reactflow.dev/) and [Svelte Flow](https://svelteflow.dev/) for SolidJS.
|
|
13
|
+
|
|
14
|
+
☣️ **Solid Flow is alpha and currently under development. The API intends to follow React/Svelte Flow closely but some things might change for the sake of SolidJS.** ☣️
|
|
15
|
+
|
|
16
|
+
## Current Unsupported Features:
|
|
17
|
+
|
|
18
|
+
- `onlyRenderVisibleElements` prop: the ability to only render visible elements on screen.
|
|
19
|
+
- Note: The prop is defined as part of `SolidFlow` but it is a no-op. During development and benchmarking, it was revealed that use of it degraded rendering performance due to the amount of work done to actually achieve the outcome of the feature. We need to innovate on the implementation to make the performance comparable (ideally better) to the normal performance of rendering all the nodes/edges on screen. As such it is a no-op prop for now.
|
|
20
|
+
- Custom MiniMap nodes: the ability to render custom node visuals in the minimap
|
|
21
|
+
- Edge Reconnect Anchors: the ability to re-connect already connected edges
|
|
22
|
+
|
|
23
|
+
## Key Features
|
|
24
|
+
|
|
25
|
+
- **Easy to use:** Seamless zooming and panning, single- and multi selection of graph elements and keyboard shortcuts are supported out of the box
|
|
26
|
+
- **Customizable:** Different node types (Input, Output, Default, Group) and edge types (Bezier, Straight, Step, SmoothStep) with full support for custom nodes and edges
|
|
27
|
+
- **Fast rendering:** Only nodes that have changed are re-rendered using SolidJS's fine-grained reactivity
|
|
28
|
+
- **Rich Plugin Ecosystem:** Background patterns, Interactive MiniMap, Zoom Controls, Node Toolbar, and Node Resizer components
|
|
29
|
+
- **Powerful Hooks:** Comprehensive set of reactive hooks for nodes, edges, viewport, connections, and data management
|
|
30
|
+
- **Full Accessibility:** Complete keyboard navigation, screen reader support, ARIA labels, and focus management
|
|
31
|
+
- **Drag & Drop:** Built-in dragging for nodes, external drag-and-drop support, and customizable drag handles
|
|
32
|
+
- **Advanced Features:** Node grouping, intersection detection, connection validation, and subflow support
|
|
33
|
+
- **TypeScript First:** Fully typed API with generic type support and IntelliSense integration
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
The easiest way to get the latest version of Solid Flow is to install it via npm, yarn or pnpm:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
npm install @dschz/solid-flow
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
This is a basic example to get you started. For more advanced examples and full API documentation, explore the playground examples included in this repository.
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import {
|
|
49
|
+
SolidFlow,
|
|
50
|
+
Controls,
|
|
51
|
+
Background,
|
|
52
|
+
MiniMap,
|
|
53
|
+
addEdge,
|
|
54
|
+
type EdgeConnection,
|
|
55
|
+
createEdgeStore,
|
|
56
|
+
createNodeStore,
|
|
57
|
+
} from "@dschz/solid-flow";
|
|
58
|
+
import "@dschz/solid-flow/styles"; // Required styles
|
|
59
|
+
|
|
60
|
+
export default function Flow() {
|
|
61
|
+
// Use createNodeStore and createEdgeStore for reactive state management
|
|
62
|
+
const [nodes, setNodes] = createNodeStore([
|
|
63
|
+
{
|
|
64
|
+
id: "1",
|
|
65
|
+
type: "input",
|
|
66
|
+
data: { label: "Input Node" },
|
|
67
|
+
position: { x: 250, y: 0 },
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "2",
|
|
71
|
+
type: "default",
|
|
72
|
+
data: { label: "Default Node" },
|
|
73
|
+
position: { x: 100, y: 100 },
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "3",
|
|
77
|
+
type: "output",
|
|
78
|
+
data: { label: "Output Node" },
|
|
79
|
+
position: { x: 250, y: 200 },
|
|
80
|
+
},
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
const [edges, setEdges] = createEdgeStore([
|
|
84
|
+
{ id: "e1-2", source: "1", target: "2" },
|
|
85
|
+
{ id: "e2-3", source: "2", target: "3" },
|
|
86
|
+
]);
|
|
87
|
+
|
|
88
|
+
const onConnect = (connection: EdgeConnection) => {
|
|
89
|
+
/**
|
|
90
|
+
* Solid Flow updates the node/edge stores internally. The user-land edge store will have the connection inserted by the time onConnect fires so we can just go ahead and update the state of it
|
|
91
|
+
*/
|
|
92
|
+
setEdges(
|
|
93
|
+
(edge) => edge.id === connection.id,
|
|
94
|
+
produce((edge) => {
|
|
95
|
+
edge.animated = true;
|
|
96
|
+
}),
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<SolidFlow nodes={nodes} edges={edges} onConnect={onConnect} fitView>
|
|
102
|
+
<Controls />
|
|
103
|
+
<MiniMap />
|
|
104
|
+
<Background variant="dots" />
|
|
105
|
+
</SolidFlow>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Core Components
|
|
111
|
+
|
|
112
|
+
### Built-in Node Types
|
|
113
|
+
|
|
114
|
+
- **InputNode** - Nodes with source handles only (starting points)
|
|
115
|
+
- **OutputNode** - Nodes with target handles only (ending points)
|
|
116
|
+
- **DefaultNode** - Standard nodes with both source and target handles
|
|
117
|
+
- **GroupNode** - Container nodes for organizing other nodes
|
|
118
|
+
|
|
119
|
+
### Built-in Edge Types
|
|
120
|
+
|
|
121
|
+
- **BezierEdge** - Smooth curved connections (default)
|
|
122
|
+
- **StraightEdge** - Direct straight line connections
|
|
123
|
+
- **StepEdge** - Right-angle step connections
|
|
124
|
+
- **SmoothStepEdge** - Rounded step connections
|
|
125
|
+
|
|
126
|
+
### Plugin Components
|
|
127
|
+
|
|
128
|
+
- **Background** - Customizable canvas backgrounds (dots, lines, cross patterns)
|
|
129
|
+
- **Controls** - Zoom in/out, fit view, lock/unlock interactions
|
|
130
|
+
- **MiniMap** - Interactive overview with viewport indicator
|
|
131
|
+
- **NodeToolbar** - Context-sensitive toolbars for nodes
|
|
132
|
+
- **NodeResizer** - Real-time node resizing with handles
|
|
133
|
+
|
|
134
|
+
## Hooks & Utilities
|
|
135
|
+
|
|
136
|
+
### Essential Hooks
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
// Main flow instance with full API
|
|
140
|
+
const solidFlow = useSolidFlow();
|
|
141
|
+
|
|
142
|
+
// Reactive access to nodes and edges
|
|
143
|
+
const nodes = useNodes();
|
|
144
|
+
const edges = useEdges();
|
|
145
|
+
|
|
146
|
+
// Viewport control and monitoring
|
|
147
|
+
const viewport = useViewport();
|
|
148
|
+
|
|
149
|
+
// Connection state during drag operations
|
|
150
|
+
const connection = useConnection();
|
|
151
|
+
|
|
152
|
+
// Reactive access to node data
|
|
153
|
+
const nodeData = useNodesData(["node-1", "node-2"]);
|
|
154
|
+
|
|
155
|
+
// Node connection information
|
|
156
|
+
const connections = useNodeConnections("node-1");
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Utility Functions
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
// Create reactive stores (replaces signals)
|
|
163
|
+
const [nodes, setNodes] = createNodeStore(initialNodes);
|
|
164
|
+
const [edges, setEdges] = createEdgeStore(initialEdges);
|
|
165
|
+
|
|
166
|
+
// Update stores with SolidJS patterns
|
|
167
|
+
import { produce } from "solid-js/store";
|
|
168
|
+
setNodes(
|
|
169
|
+
(node) => node.id === "1",
|
|
170
|
+
produce((node) => {
|
|
171
|
+
node.position.x += 20;
|
|
172
|
+
}),
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
// Add new connections
|
|
176
|
+
setEdges(addEdge(connection, edges));
|
|
177
|
+
|
|
178
|
+
// Coordinate transformations (via useSolidFlow)
|
|
179
|
+
const { screenToFlowPosition, flowToScreenPosition } = useSolidFlow();
|
|
180
|
+
|
|
181
|
+
// Node/edge utilities
|
|
182
|
+
getNodesBounds(nodes);
|
|
183
|
+
getIntersectingNodes(node, nodes);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Advanced Features
|
|
187
|
+
|
|
188
|
+
### Custom Nodes and Edges
|
|
189
|
+
|
|
190
|
+
Create fully customized components with multiple handles:
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
import { Handle, type NodeProps } from "@dschz/solid-flow";
|
|
194
|
+
|
|
195
|
+
// Type-safe custom node component
|
|
196
|
+
function CustomNode(props: NodeProps<{ label: string }, "custom">) {
|
|
197
|
+
return (
|
|
198
|
+
<div class="custom-node" style={{ padding: "10px", background: "white" }}>
|
|
199
|
+
<Handle type="target" position="top />
|
|
200
|
+
<div>{props.data.label}</div>
|
|
201
|
+
<Handle type="source" position="bottom" id="output-a" />
|
|
202
|
+
<Handle type="source" position="bottom id="output-b" style={{ left: "80%" }} />
|
|
203
|
+
</div>
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Create type-safe node types
|
|
208
|
+
const nodeTypes = {
|
|
209
|
+
custom: CustomNode,
|
|
210
|
+
} satisfies NodeTypes;
|
|
211
|
+
|
|
212
|
+
// Use with typed store
|
|
213
|
+
const [nodes] = createNodeStore<typeof nodeTypes>([...]);
|
|
214
|
+
|
|
215
|
+
<SolidFlow nodeTypes={nodeTypes} nodes={nodes} ... />
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Connection Validation
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
import { type Connection } from "@dschz/solid-flow";
|
|
222
|
+
|
|
223
|
+
const isValidConnection = (connection: Connection) => {
|
|
224
|
+
// Custom validation logic
|
|
225
|
+
return connection.source !== connection.target;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const onConnect = (connection: Connection) => {
|
|
229
|
+
console.log("New connection:", connection);
|
|
230
|
+
setEdges(addEdge(connection, edges));
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
<SolidFlow
|
|
234
|
+
isValidConnection={isValidConnection}
|
|
235
|
+
onConnect={onConnect}
|
|
236
|
+
...
|
|
237
|
+
/>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Event Handling
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
<SolidFlow
|
|
244
|
+
onNodeClick={(event, node) => console.log("Node clicked:", node)}
|
|
245
|
+
onNodeDrag={(event, node) => console.log("Node dragged:", node)}
|
|
246
|
+
onEdgeClick={(event, edge) => console.log("Edge clicked:", edge)}
|
|
247
|
+
onPaneClick={(event) => console.log("Pane clicked")}
|
|
248
|
+
onSelectionChange={(params) => console.log("Selection changed:", params)}
|
|
249
|
+
/>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Accessibility
|
|
253
|
+
|
|
254
|
+
Solid Flow includes comprehensive accessibility features:
|
|
255
|
+
|
|
256
|
+
- Full keyboard navigation support
|
|
257
|
+
- Screen reader compatibility with ARIA labels
|
|
258
|
+
- Focus management and visual indicators
|
|
259
|
+
- High contrast and color mode support
|
|
260
|
+
- Customizable keyboard shortcuts
|
|
261
|
+
|
|
262
|
+
## Performance
|
|
263
|
+
|
|
264
|
+
- **Reactive Updates**: Only re-renders components when their specific data changes
|
|
265
|
+
- **Viewport Optimization**: Option to render only visible elements (coming soon)
|
|
266
|
+
- **Memory Efficient**: Optimized data structures for large graphs
|
|
267
|
+
- **Stress Tested**: Handles hundreds of nodes smoothly
|
|
268
|
+
|
|
269
|
+
## Examples
|
|
270
|
+
|
|
271
|
+
The repository includes a comprehensive playground with 25+ examples:
|
|
272
|
+
|
|
273
|
+
- **Basic Usage** - Simple flows and interactions
|
|
274
|
+
- **Custom Nodes** - Creating specialized node types
|
|
275
|
+
- **Edge Types** - Different connection styles
|
|
276
|
+
- **Drag & Drop** - External elements and node creation
|
|
277
|
+
- **Validation** - Connection rules and constraints
|
|
278
|
+
- **Subflows** - Hierarchical node organization
|
|
279
|
+
- **Performance** - Large dataset handling
|
|
280
|
+
- **Accessibility** - Keyboard navigation and screen readers
|
|
281
|
+
|
|
282
|
+
Run the examples locally:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
bun start
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Contributing: Getting Started
|
|
289
|
+
|
|
290
|
+
Some pre-requisites before install dependencies:
|
|
291
|
+
|
|
292
|
+
- Install Node Version Manager (NVM)
|
|
293
|
+
```bash
|
|
294
|
+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
|
|
295
|
+
```
|
|
296
|
+
- Install Bun
|
|
297
|
+
```bash
|
|
298
|
+
curl -fsSL https://bun.sh/install | bash
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Installing Dependencies
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
nvm use
|
|
305
|
+
bun install
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Local Development Build
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
bun start
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Linting & Formatting
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
bun run lint # checks source for lint violations
|
|
318
|
+
bun run format # checks source for format violations
|
|
319
|
+
|
|
320
|
+
bun run lint:fix # fixes lint violations
|
|
321
|
+
bun run format:fix # fixes format violations
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Contributing
|
|
325
|
+
|
|
326
|
+
The only requirements when contributing are:
|
|
327
|
+
|
|
328
|
+
- You keep a clean git history in your branch
|
|
329
|
+
- rebasing `main` instead of making merge commits.
|
|
330
|
+
- Using proper commit message formats that adhere to [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/)
|
|
331
|
+
- Additionally, squashing (via rebase) commits that are not [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/)
|
|
332
|
+
- CI checks pass before merging into `main`
|