@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 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](https://img.shields.io/badge/license-MIT-green)](LICENSE)
8
+ [![npm](https://img.shields.io/npm/v/@dschz/solid-flow?color=blue)](https://www.npmjs.com/package/@dschz/solid-flow)
9
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@dschz/solid-flow)](https://bundlephobia.com/package/@dschz/solid-flow)
10
+ [![CI](https://github.com/dsnchz/solid-flow/actions/workflows/ci.yaml/badge.svg)](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`