@infinit-canvas/react 0.1.8 → 0.1.11
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 +129 -37
- package/dist/react-infinite-canvas.cjs +513 -476
- package/dist/react-infinite-canvas.js +3273 -2806
- package/package.json +4 -2
- package/src/types.d.ts +88 -11
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Awais Shah
|
|
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
CHANGED
|
@@ -1,62 +1,154 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @infinit-canvas/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@infinit-canvas/react)
|
|
4
|
+
[](https://github.com/awaisshah228/infinit-canvas/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
A high-performance infinite canvas React component powered by **OffscreenCanvas + Web Workers**. Drop-in React Flow compatible API — but renders on a canvas for **10x better performance** at scale.
|
|
7
|
+
|
|
8
|
+
**5,000+ nodes at 60fps** vs React Flow's ~500 before lag.
|
|
9
|
+
|
|
10
|
+
**npm:** [https://www.npmjs.com/package/@infinit-canvas/react](https://www.npmjs.com/package/@infinit-canvas/react)
|
|
11
|
+
**GitHub:** [https://github.com/awaisshah228/infinit-canvas](https://github.com/awaisshah228/infinit-canvas)
|
|
4
12
|
|
|
5
13
|
## Install
|
|
6
14
|
|
|
7
15
|
```bash
|
|
8
|
-
npm install
|
|
16
|
+
npm install @infinit-canvas/react
|
|
9
17
|
```
|
|
10
18
|
|
|
11
|
-
##
|
|
19
|
+
## Quick Start
|
|
12
20
|
|
|
13
21
|
```jsx
|
|
14
|
-
import { InfiniteCanvas } from '
|
|
15
|
-
import '
|
|
22
|
+
import { InfiniteCanvas, useNodesState, useEdgesState, addEdge, Controls, MiniMap, Background } from '@infinit-canvas/react';
|
|
23
|
+
import '@infinit-canvas/react/styles.css';
|
|
24
|
+
|
|
25
|
+
const initialNodes = [
|
|
26
|
+
{ id: '1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } },
|
|
27
|
+
{ id: '2', position: { x: 250, y: 100 }, data: { label: 'Node 2' } },
|
|
28
|
+
];
|
|
16
29
|
|
|
17
|
-
const
|
|
18
|
-
{
|
|
19
|
-
{ x: 320, y: 140, w: 160, h: 90, title: 'Note B', body: 'World!' },
|
|
30
|
+
const initialEdges = [
|
|
31
|
+
{ id: 'e1-2', source: '1', target: '2' },
|
|
20
32
|
];
|
|
21
33
|
|
|
22
34
|
function App() {
|
|
23
|
-
|
|
35
|
+
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
|
36
|
+
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
|
37
|
+
const onConnect = (conn) => setEdges((eds) => addEdge(conn, eds));
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<InfiniteCanvas
|
|
41
|
+
nodes={nodes}
|
|
42
|
+
edges={edges}
|
|
43
|
+
onNodesChange={onNodesChange}
|
|
44
|
+
onEdgesChange={onEdgesChange}
|
|
45
|
+
onConnect={onConnect}
|
|
46
|
+
height="500px"
|
|
47
|
+
>
|
|
48
|
+
<Controls />
|
|
49
|
+
<MiniMap />
|
|
50
|
+
<Background variant="dots" />
|
|
51
|
+
</InfiniteCanvas>
|
|
52
|
+
);
|
|
24
53
|
}
|
|
25
54
|
```
|
|
26
55
|
|
|
27
|
-
##
|
|
56
|
+
## Why This?
|
|
57
|
+
|
|
58
|
+
| | React Flow | @infinit-canvas/react |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| Rendering | DOM (React divs + SVG) | OffscreenCanvas + Web Worker |
|
|
61
|
+
| Max nodes (60fps) | ~500 | 5,000+ |
|
|
62
|
+
| Main thread | Blocked during render | Always free |
|
|
63
|
+
| Custom nodes | React components | Hybrid: canvas + DOM overlay |
|
|
64
|
+
| API | React Flow API | Same API (drop-in compatible) |
|
|
65
|
+
|
|
66
|
+
## Features
|
|
67
|
+
|
|
68
|
+
- **Full React Flow API** — nodes, edges, handles, connections, selection, drag, zoom, pan
|
|
69
|
+
- **Custom node & edge types** — use any React component
|
|
70
|
+
- **Built-in components** — Controls, MiniMap, Background, Panel, Handle, NodeResizer, NodeToolbar, EdgeLabelRenderer, ViewportPortal
|
|
71
|
+
- **All hooks** — useReactFlow, useNodes, useEdges, useViewport, useConnection, useNodesData, useOnViewportChange, useOnSelectionChange, useKeyPress, useStore, useStoreApi, + more
|
|
72
|
+
- **Sub-flows** — parentId, extent: 'parent'
|
|
73
|
+
- **Connection modes** — strict/loose, click-to-connect, validation
|
|
74
|
+
- **Selection** — click, Shift+click multi-select, Ctrl+A, selection box, selection drag events
|
|
75
|
+
- **Edge types** — bezier, straight, step, smoothstep, animated, labels
|
|
76
|
+
- **Edge routing** — automatic obstacle avoidance
|
|
77
|
+
- **Snap to grid** — configurable grid snapping
|
|
78
|
+
- **Undo/redo** — built-in history management
|
|
79
|
+
- **Delete validation** — onBeforeDelete async callback
|
|
80
|
+
- **Error handling** — onError callback
|
|
81
|
+
- **noDragClassName / noPanClassName** — prevent drag/pan on specific elements
|
|
82
|
+
- **Elevate on select** — bring nodes/edges to front on selection
|
|
83
|
+
- **Node virtualization** — only visible custom nodes are mounted in DOM
|
|
84
|
+
- **Frustum culling** — spatial grid index for O(visible) rendering
|
|
28
85
|
|
|
29
|
-
|
|
30
|
-
|------|---------|-------------|
|
|
31
|
-
| `cards` | `[]` | Array of `{ x, y, w, h, title, body }` |
|
|
32
|
-
| `dark` | auto | Force dark/light mode |
|
|
33
|
-
| `gridSize` | `40` | Grid cell size in px |
|
|
34
|
-
| `zoomMin` / `zoomMax` | `0.1` / `4` | Zoom limits |
|
|
35
|
-
| `initialCamera` | `{ x:0, y:0, zoom:1 }` | Starting position |
|
|
36
|
-
| `onHudUpdate` | - | Callback: `{ wx, wy, zoom, renderMs, fps, visible }` |
|
|
37
|
-
| `showHud` / `showHint` | `true` | Toggle overlays |
|
|
38
|
-
| `width` / `height` | `'100%'` / `'420px'` | Container size |
|
|
39
|
-
| `className` / `style` | - | Custom styling |
|
|
40
|
-
| `children` | - | Render inside canvas wrapper |
|
|
41
|
-
|
|
42
|
-
## Hook API
|
|
86
|
+
## Props
|
|
43
87
|
|
|
44
88
|
```jsx
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
89
|
+
<InfiniteCanvas
|
|
90
|
+
// Data
|
|
91
|
+
nodes={nodes}
|
|
92
|
+
edges={edges}
|
|
93
|
+
onNodesChange={onNodesChange}
|
|
94
|
+
onEdgesChange={onEdgesChange}
|
|
95
|
+
onConnect={onConnect}
|
|
96
|
+
|
|
97
|
+
// Types
|
|
98
|
+
nodeTypes={nodeTypes}
|
|
99
|
+
edgeTypes={edgeTypes}
|
|
100
|
+
|
|
101
|
+
// Events
|
|
102
|
+
onNodeClick onNodeDoubleClick onNodeContextMenu
|
|
103
|
+
onNodeDragStart onNodeDrag onNodeDragStop
|
|
104
|
+
onEdgeClick onEdgeDoubleClick
|
|
105
|
+
onPaneClick onPaneContextMenu
|
|
106
|
+
onSelectionChange
|
|
107
|
+
onSelectionDragStart onSelectionDrag onSelectionDragStop
|
|
108
|
+
onConnectStart onConnectEnd
|
|
109
|
+
onMoveStart onMove onMoveEnd
|
|
110
|
+
onInit onDelete onBeforeDelete onError
|
|
111
|
+
|
|
112
|
+
// Behavior
|
|
113
|
+
nodesDraggable nodesConnectable elementsSelectable
|
|
114
|
+
connectionMode="loose" connectOnClick={false}
|
|
115
|
+
snapToGrid snapGrid={[15, 15]}
|
|
116
|
+
elevateNodesOnSelect elevateEdgesOnSelect
|
|
117
|
+
noDragClassName="nodrag" noPanClassName="nopan"
|
|
118
|
+
deleteKeyCode="Delete"
|
|
119
|
+
isValidConnection={fn}
|
|
120
|
+
|
|
121
|
+
// Viewport
|
|
122
|
+
fitView initialCamera={{ x: 0, y: 0, zoom: 1 }}
|
|
123
|
+
zoomMin={0.1} zoomMax={4}
|
|
124
|
+
panOnScroll zoomOnScroll zoomOnPinch zoomOnDoubleClick
|
|
125
|
+
translateExtent autoPanOnNodeDrag
|
|
126
|
+
|
|
127
|
+
// Appearance
|
|
128
|
+
dark gridSize={40} width="100%" height="500px"
|
|
129
|
+
/>
|
|
49
130
|
```
|
|
50
131
|
|
|
51
|
-
##
|
|
132
|
+
## Hooks
|
|
133
|
+
|
|
134
|
+
| Hook | Description |
|
|
135
|
+
|---|---|
|
|
136
|
+
| `useNodesState` | useState + applyNodeChanges |
|
|
137
|
+
| `useEdgesState` | useState + applyEdgeChanges |
|
|
138
|
+
| `useReactFlow` | Imperative API (fitView, zoomIn, getNodes, setNodes, etc.) |
|
|
139
|
+
| `useNodes` / `useEdges` | Read current nodes/edges |
|
|
140
|
+
| `useViewport` | Read { x, y, zoom } |
|
|
141
|
+
| `useConnection` | Connection state while dragging |
|
|
142
|
+
| `useOnViewportChange` | Subscribe to viewport changes |
|
|
143
|
+
| `useOnSelectionChange` | Subscribe to selection changes |
|
|
144
|
+
| `useKeyPress` | Track key state |
|
|
145
|
+
| `useStore` / `useStoreApi` | Direct store access |
|
|
146
|
+
| `useUndoRedo` | Undo/redo history |
|
|
147
|
+
|
|
148
|
+
## Utilities
|
|
52
149
|
|
|
53
|
-
|
|
54
|
-
- **Batched multi-pass rendering** (~10 draw calls for any number of cards)
|
|
55
|
-
- **Level of Detail** — text/shadows hidden at low zoom
|
|
56
|
-
- **Web Worker rendering** — main thread never blocked
|
|
57
|
-
- **Pre-computed colors** and font constants
|
|
58
|
-
- **Throttled HUD** updates (100ms)
|
|
150
|
+
`applyNodeChanges` · `applyEdgeChanges` · `addEdge` · `isNode` · `isEdge` · `getConnectedEdges` · `getIncomers` · `getOutgoers` · `getNodesBounds` · `getBezierPath` · `getSmoothStepPath` · `getStraightPath` · `getSimpleBezierPath` · `snapPosition` · `reconnectEdge`
|
|
59
151
|
|
|
60
152
|
## License
|
|
61
153
|
|
|
62
|
-
MIT
|
|
154
|
+
[MIT](./LICENSE)
|