@quantumwake/kgraph 0.1.2
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/LICENSE +21 -0
- package/README.md +245 -0
- package/dist/index.cjs +1347 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +309 -0
- package/dist/index.d.ts +309 -0
- package/dist/index.js +1328 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 QuantumWake
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# @quantumwake/kgraph
|
|
2
|
+
|
|
3
|
+
A lightweight, zero-dependency React graph canvas. Build node-based editors, pipelines, and diagrams with a familiar API — no Zustand, no d3, no CSS imports required.
|
|
4
|
+
|
|
5
|
+
If you've used ReactFlow, you'll feel right at home. If you haven't, you'll be up and running in 5 minutes.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Why KGraph?
|
|
10
|
+
|
|
11
|
+
| | ReactFlow | KGraph |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Runtime deps | Zustand + d3-selection + d3-zoom + d3-drag | **None** |
|
|
14
|
+
| CSS import | Required | **Not needed** |
|
|
15
|
+
| Bundle size | ~150KB+ | **~42KB** |
|
|
16
|
+
| Source | 100+ files, monorepo | **12 files, ~2K LOC** |
|
|
17
|
+
| Mental model | Zustand store + d3 transforms | **React context + useState** |
|
|
18
|
+
| API surface | 19 hooks, 60+ types | **2 hooks, 15 types** |
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @quantumwake/kgraph
|
|
24
|
+
# or
|
|
25
|
+
yarn add @quantumwake/kgraph
|
|
26
|
+
# or
|
|
27
|
+
pnpm add @quantumwake/kgraph
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Requires React 17+. That's it — no CSS files to import, no provider wrappers to add.
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import { useState } from 'react';
|
|
36
|
+
import {
|
|
37
|
+
KGraphCanvas,
|
|
38
|
+
applyNodeChanges,
|
|
39
|
+
applyEdgeChanges,
|
|
40
|
+
} from '@quantumwake/kgraph';
|
|
41
|
+
import type { KGraphNode, KGraphEdge, KGraphConnection } from '@quantumwake/kgraph';
|
|
42
|
+
|
|
43
|
+
function MyGraph() {
|
|
44
|
+
const [nodes, setNodes] = useState<KGraphNode[]>([
|
|
45
|
+
{ id: '1', type: 'default', position: { x: 0, y: 0 }, data: { label: 'Hello' } },
|
|
46
|
+
{ id: '2', type: 'default', position: { x: 200, y: 120 }, data: { label: 'World' } },
|
|
47
|
+
]);
|
|
48
|
+
const [edges, setEdges] = useState<KGraphEdge[]>([
|
|
49
|
+
{ id: 'e1', source: '1', target: '2' },
|
|
50
|
+
]);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div style={{ width: '100%', height: 600 }}>
|
|
54
|
+
<KGraphCanvas
|
|
55
|
+
nodes={nodes}
|
|
56
|
+
edges={edges}
|
|
57
|
+
onNodesChange={c => setNodes(applyNodeChanges(c, nodes))}
|
|
58
|
+
onEdgesChange={c => setEdges(applyEdgeChanges(c, edges))}
|
|
59
|
+
onConnect={(conn: KGraphConnection) =>
|
|
60
|
+
setEdges(prev => [...prev, { id: `e-${Date.now()}`, ...conn }])
|
|
61
|
+
}
|
|
62
|
+
fitView
|
|
63
|
+
/>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
That gives you pan, zoom, drag, snap-to-grid, selection, keyboard delete, a minimap, directed arrows, and a dot grid background — all out of the box.
|
|
70
|
+
|
|
71
|
+
## Features
|
|
72
|
+
|
|
73
|
+
- **Zero dependencies** — peer dep on React, nothing else
|
|
74
|
+
- **ReactFlow-compatible API** — `applyNodeChanges`, `applyEdgeChanges`, `getBezierPath`
|
|
75
|
+
- **Custom nodes & edges** — bring your own React components
|
|
76
|
+
- **Connection drawing** — drag from source handle to target handle
|
|
77
|
+
- **Interactive handles** — visible dots with hover effects, crosshair cursor on sources
|
|
78
|
+
- **Directed arrows** — SVG markers on all edges by default
|
|
79
|
+
- **MiniMap** — click-to-navigate overview
|
|
80
|
+
- **Dot grid background** — configurable gap
|
|
81
|
+
- **Edge labels** — zoom-invariant HTML overlays
|
|
82
|
+
- **Viewport controls** — `useKGraph()` hook for `fitView`, `zoomIn`, `zoomOut`, `zoomTo`
|
|
83
|
+
- **Drag & drop** — `onDrop` callback with canvas-space coordinates
|
|
84
|
+
- **Multi-select** — Shift/Cmd+click
|
|
85
|
+
- **Keyboard shortcuts** — Delete/Backspace to remove selected elements
|
|
86
|
+
- **Snap-to-grid** — configurable grid size
|
|
87
|
+
- **Fully typed** — TypeScript declarations included
|
|
88
|
+
|
|
89
|
+
## Custom Nodes
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import { Handle } from '@quantumwake/kgraph';
|
|
93
|
+
import type { NodeComponentProps } from '@quantumwake/kgraph';
|
|
94
|
+
|
|
95
|
+
const MyNode: React.FC<NodeComponentProps> = ({ data, selected }) => (
|
|
96
|
+
<div style={{
|
|
97
|
+
padding: 16, borderRadius: 8,
|
|
98
|
+
border: `2px solid ${selected ? '#60a5fa' : '#333'}`,
|
|
99
|
+
background: '#1a1a2e', color: '#fff',
|
|
100
|
+
}}>
|
|
101
|
+
<Handle id="target-1" type="target" position="top" />
|
|
102
|
+
<h3>{data.title}</h3>
|
|
103
|
+
<p>{data.description}</p>
|
|
104
|
+
<Handle id="source-4" type="source" position="bottom" />
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// Register it:
|
|
109
|
+
<KGraphCanvas nodeTypes={{ myNode: MyNode }} ... />
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Handle IDs** map to positions: `*-1` = top, `*-2` = left, `*-3` = right, `*-4` = bottom.
|
|
113
|
+
|
|
114
|
+
Handles are visible by default (purple dots that grow on hover). Pass `style={{ background: '#22c55e', borderColor: '#4ade80' }}` to customize colors.
|
|
115
|
+
|
|
116
|
+
## Custom Edges
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
import { getBezierPath } from '@quantumwake/kgraph';
|
|
120
|
+
import type { EdgeComponentProps } from '@quantumwake/kgraph';
|
|
121
|
+
|
|
122
|
+
const DashedEdge: React.FC<EdgeComponentProps> = (props) => {
|
|
123
|
+
const [path] = getBezierPath(props);
|
|
124
|
+
return (
|
|
125
|
+
<g>
|
|
126
|
+
<path d={path} fill="none" stroke="transparent" strokeWidth={20} />
|
|
127
|
+
<path d={path} fill="none" stroke="#7c3aed" strokeWidth={2}
|
|
128
|
+
strokeDasharray="8 4"
|
|
129
|
+
markerEnd="url(#kgraph-arrow)" />
|
|
130
|
+
</g>
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
<KGraphCanvas edgeTypes={{ dashed: DashedEdge }} ... />
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Arrow markers (`#kgraph-arrow` and `#kgraph-arrow-selected`) are defined automatically by KGraphCanvas.
|
|
138
|
+
|
|
139
|
+
## Hooks
|
|
140
|
+
|
|
141
|
+
### `useKGraph()`
|
|
142
|
+
|
|
143
|
+
Available inside any child of `<KGraphCanvas>`:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
const {
|
|
147
|
+
fitView, // (options?) => void
|
|
148
|
+
zoomIn, // () => void
|
|
149
|
+
zoomOut, // () => void
|
|
150
|
+
zoomTo, // (level: number) => void
|
|
151
|
+
getViewport, // () => { x, y, zoom }
|
|
152
|
+
setViewport, // (viewport | updater) => void
|
|
153
|
+
screenToCanvasPosition, // (clientX, clientY) => { x, y }
|
|
154
|
+
getNodes, // () => KGraphNode[]
|
|
155
|
+
getEdges, // () => KGraphEdge[]
|
|
156
|
+
} = useKGraph();
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `useKGraphContext()`
|
|
160
|
+
|
|
161
|
+
Full internal context — `containerRef`, handle registration, `canvasToScreenPosition`, etc. Use this for advanced integrations.
|
|
162
|
+
|
|
163
|
+
## Props Reference
|
|
164
|
+
|
|
165
|
+
| Prop | Type | Default | Description |
|
|
166
|
+
|---|---|---|---|
|
|
167
|
+
| `nodes` | `KGraphNode[]` | required | Node array |
|
|
168
|
+
| `edges` | `KGraphEdge[]` | required | Edge array |
|
|
169
|
+
| `onNodesChange` | `(changes) => void` | — | Node change callback |
|
|
170
|
+
| `onEdgesChange` | `(changes) => void` | — | Edge change callback |
|
|
171
|
+
| `onConnect` | `(connection) => void` | — | New connection callback |
|
|
172
|
+
| `onNodeClick` | `(event, node) => void` | — | Node click handler |
|
|
173
|
+
| `onEdgeClick` | `(event, edge) => void` | — | Edge click handler |
|
|
174
|
+
| `onPaneClick` | `(event) => void` | — | Background click handler |
|
|
175
|
+
| `onDrop` | `(event, position) => void` | — | Drop with canvas coordinates |
|
|
176
|
+
| `nodeTypes` | `Record<string, Component>` | `{}` | Custom node components |
|
|
177
|
+
| `edgeTypes` | `Record<string, Component>` | `{}` | Custom edge components |
|
|
178
|
+
| `snapToGrid` | `boolean` | `true` | Snap node positions to grid |
|
|
179
|
+
| `snapGrid` | `[number, number]` | `[16, 16]` | Grid cell size in px |
|
|
180
|
+
| `panOnDrag` | `boolean` | `true` | Enable canvas panning |
|
|
181
|
+
| `zoomOnScroll` | `boolean` | `true` | Enable scroll/pinch zoom |
|
|
182
|
+
| `nodesDraggable` | `boolean` | `true` | Allow node dragging |
|
|
183
|
+
| `nodesConnectable` | `boolean` | `true` | Allow connection drawing |
|
|
184
|
+
| `elementsSelectable` | `boolean` | `true` | Allow click-to-select |
|
|
185
|
+
| `fitView` | `boolean` | `false` | Auto-fit viewport on mount |
|
|
186
|
+
| `showMiniMap` | `boolean` | `true` | Show minimap overlay |
|
|
187
|
+
| `showBackground` | `boolean` | `true` | Show dot grid |
|
|
188
|
+
| `backgroundGap` | `number` | `32` | Dot grid spacing |
|
|
189
|
+
| `minZoom` | `number` | `0.1` | Minimum zoom level |
|
|
190
|
+
| `maxZoom` | `number` | `4` | Maximum zoom level |
|
|
191
|
+
|
|
192
|
+
## Examples
|
|
193
|
+
|
|
194
|
+
9 interactive examples ship as a runnable Vite app:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
cd examples && npm install && npm run dev
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Open [localhost:5173](http://localhost:5173) — sidebar navigation across all demos:
|
|
201
|
+
|
|
202
|
+
| Example | What it shows |
|
|
203
|
+
|---|---|
|
|
204
|
+
| **Basic Graph** | Simplest usage — 3 nodes, 2 edges |
|
|
205
|
+
| **Custom Nodes** | Input/Processor/Output types with colored multi-handle |
|
|
206
|
+
| **Custom Edges** | Labeled, animated, and success edge styles |
|
|
207
|
+
| **Drag & Drop** | Palette panel, drag to create nodes |
|
|
208
|
+
| **Viewport Controls** | Programmatic zoom/fit toolbar via `useKGraph()` |
|
|
209
|
+
| **Interactive Callbacks** | Real-time event log for all interactions |
|
|
210
|
+
| **Canvas Options** | Runtime toggle of every canvas prop |
|
|
211
|
+
| **Large Graph** | 80-node grid for performance testing |
|
|
212
|
+
| **MiniMap & Background** | Category-colored pipeline with minimap |
|
|
213
|
+
|
|
214
|
+
All examples include drag & drop, right-click context menus, and connection drawing.
|
|
215
|
+
|
|
216
|
+
See [EXAMPLES.md](./EXAMPLES.md) for detailed docs on each one.
|
|
217
|
+
|
|
218
|
+
## Migrating from ReactFlow
|
|
219
|
+
|
|
220
|
+
KGraph's API is designed for easy migration:
|
|
221
|
+
|
|
222
|
+
- `<ReactFlow>` → `<KGraphCanvas>`
|
|
223
|
+
- `<ReactFlowProvider>` → not needed (provider is built in)
|
|
224
|
+
- `useReactFlow()` → `useKGraph()`
|
|
225
|
+
- `applyNodeChanges` / `applyEdgeChanges` → same function names, same behavior
|
|
226
|
+
- `getBezierPath` → same function name, same return signature
|
|
227
|
+
- `Node<T>` → `KGraphNode`, `Edge<T>` → `KGraphEdge`
|
|
228
|
+
- Remove your ReactFlow CSS import — KGraph uses inline styles
|
|
229
|
+
|
|
230
|
+
See [COMPARISON.md](./COMPARISON.md) for a full feature matrix against ReactFlow, React Diagrams, Reaflow, and X6.
|
|
231
|
+
|
|
232
|
+
## Contributing
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
git clone https://github.com/quantumwake/kgraph.git
|
|
236
|
+
cd kgraph
|
|
237
|
+
npm install
|
|
238
|
+
npm run build # builds dist/
|
|
239
|
+
npm run dev # watch mode
|
|
240
|
+
npm run lint # type-check
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
[MIT](./LICENSE)
|