nx-react-sigma
v1.0.0
Published
A powerful React wrapper for Sigma.js that provides interactive graph visualizations with advanced layout management and user interactions
Readme
nx-react-sigma
A powerful React wrapper for Sigma.js that provides a clean, type-safe interface for creating interactive graph visualizations with advanced layout management and user interactions.
🚀 Features
- React Integration: Seamless React components and hooks for Sigma.js
- TypeScript Support: Full type safety with comprehensive TypeScript definitions
- Layout Management: Built-in support for multiple layout algorithms (Force, ForceAtlas2, Noverlap)
- Interactive Features: Click, hover, drag-and-drop, and zoom interactions
- Command Pattern: Undo/redo functionality with command history
- Context-Based Architecture: Clean separation of concerns using React Context
- Performance Optimized: Context selectors for minimal re-renders
- Modular Design: Clean Architecture with well-defined layers
📦 Installation
# Using pnpm (recommended for monorepo)
pnpm add nx-react-sigma
# Using npm
npm install nx-react-sigma
# Using yarn
yarn add nx-react-sigmaPeer Dependencies
This package requires the following peer dependencies:
{
"@sigma/edge-curve": "^3.1.0",
"chroma-js": "^3.1.2",
"graphology": "^0.25.4",
"graphology-layout-force": "^0.2.4",
"graphology-layout-forceatlas2": "^0.10.1",
"graphology-layout-noverlap": "^0.4.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sigma": "3.0.2",
"use-context-selector": "^2.0.0"
}🎯 Quick Start
Basic Usage
import React from 'react';
import { MultiDirectedGraph } from 'graphology';
import { SigmaContainer } from 'nx-react-sigma';
// Create a simple graph
const graph = new MultiDirectedGraph();
graph.addNode('node1', { x: 0, y: 0, size: 10, color: '#ff0000' });
graph.addNode('node2', { x: 100, y: 100, size: 15, color: '#00ff00' });
graph.addEdge('node1', 'node2', { color: '#cccccc' });
function App() {
return (
<div style={{ width: '800px', height: '600px' }}>
<SigmaContainer graph={graph}>{/* Your graph content here */}</SigmaContainer>
</div>
);
}
export default App;Advanced Usage with Interactions
import React, { useEffect } from 'react';
import { MultiDirectedGraph } from 'graphology';
import {
SigmaContainer,
useClickNode,
useLayoutForce,
useDragAndDropInteraction,
} from 'nx-react-sigma';
const GraphComponent = () => {
// Enable interactions
useClickNode();
useDragAndDropInteraction();
// Apply force layout
const layout = useLayoutForce({
settings: {
attraction: 0.0005,
repulsion: 0.1,
},
});
useEffect(() => {
if (layout) {
layout.start();
return () => layout.stop();
}
}, [layout]);
return null;
};
function App() {
const graph = new MultiDirectedGraph();
// ... populate your graph
return (
<SigmaContainer graph={graph}>
<GraphComponent />
</SigmaContainer>
);
}🏗️ Architecture
This package follows Clean Architecture principles with clear separation of concerns:
├── components/ # Presentation Layer
│ └── container/ # SigmaContainer component
├── contexts/ # Application Layer
│ └── SigmaContext/ # Context provider and hooks
├── use-cases/ # Application Layer
│ ├── interactions/ # User interaction handlers
│ ├── layout/ # Layout management
│ └── nx-query/ # Query operations
├── entities/ # Domain Layer
│ ├── interactions/ # Interaction models
│ ├── layout/ # Layout models
│ ├── nx-graph/ # Graph models
│ └── query/ # Query models
├── graphology/ # Infrastructure Layer
│ ├── command/ # Command pattern implementation
│ └── layouts/ # Layout algorithms
├── factory/ # Factory patterns
├── helpers/ # Utility functions
└── hooks/ # Shared hooks📚 API Reference
Components
SigmaContainer
The main container component that initializes a Sigma instance.
interface SigmaContainerProps {
graph: MultiDirectedGraph;
settings?: Partial<Settings>;
children?: ReactNode | ((containerRef: MutableRefObject<HTMLDivElement | null>) => ReactNode);
layoutTimeoutMil?: number;
}
export interface SigmaContainerRef {
getSigmaInstance: () => Sigma | undefined;
restart: () => void;
}Props:
graph: Graphology MultiDirectedGraph instancesettings: Optional Sigma.js settingschildren: Child components or render functionlayoutTimeoutMil: Timeout for layout operations (default: 2000ms)
Ref Methods:
getSigmaInstance(): Returns the Sigma instancerestart(): Restarts the Sigma instance
Hooks
Context Hooks
// Access the Sigma instance
const sigma = useSigma();
// Access the graph
const graph = useGraph();
// Access layout manager
const layoutManager = useLayoutManager();
// Access graph manager
const graphManager = useGraphManager();Interaction Hooks
// Node click interactions
useClickNode();
// Drag and drop functionality
useDragAndDropInteraction();
// Hover interactions
useEdgeNodeHoverInteraction();
// Zoom to specific nodes
const zoomToNode = useZoomToNode();
const zoomToNodes = useZoomToNodes();
// Restart Sigma instance
const restart = useSigmaRestart();Layout Hooks
// Force layout
const forceLayout = useLayoutForce(settings);
// ForceAtlas2 layout
const forceAtlas2Layout = useLayoutForceAtlas2(settings);
// Noverlap layout (prevents node overlap)
const noverlapLayout = useLayoutNoverlap(settings);
// Index parallel edges
useIndexParallelEdges();Layout Management
Force Layout
import { useLayoutForce } from 'nx-react-sigma';
const MyComponent = () => {
const layout = useLayoutForce({
attraction: 0.0005,
repulsion: 0.1,
gravity: 0.0001,
inertia: 0.6,
maxMove: 200,
});
useEffect(() => {
if (layout) {
layout.start();
return () => layout.stop();
}
}, [layout]);
return null;
};ForceAtlas2 Layout
import { useLayoutForceAtlas2 } from 'nx-react-sigma';
const MyComponent = () => {
const layout = useLayoutForceAtlas2({
scalingRatio: 10,
gravity: 1,
strongGravityMode: false,
slowDown: 1,
});
useEffect(() => {
if (layout) {
layout.start();
return () => layout.stop();
}
}, [layout]);
return null;
};Command Pattern
The package includes a command pattern implementation for undo/redo functionality:
import { useGraphManager } from 'nx-react-sigma';
const MyComponent = () => {
const graphManager = useGraphManager();
const addNode = () => {
const command = graphManager?.getCommandManager();
command?.execute('addNode', {
key: 'newNode',
attributes: { x: 0, y: 0, size: 10 },
});
};
const undo = () => {
const command = graphManager?.getCommandManager();
command?.undo();
};
const redo = () => {
const command = graphManager?.getCommandManager();
command?.redo();
};
return (
<div>
<button onClick={addNode}>Add Node</button>
<button onClick={undo}>Undo</button>
<button onClick={redo}>Redo</button>
</div>
);
};Available Commands
addNode: Add a new node to the graphremoveNode: Remove a node from the graphaddEdge: Add a new edge to the graphremoveEdge: Remove an edge from the graphupdateNodeAttributes: Update node attributesupdateEdgeAttributes: Update edge attributesremoveAllNodes: Clear all nodes from the graph
🎨 Styling
The package includes CSS modules for styling. Import the styles:
import 'nx-react-sigma/dist/style.css';Custom Styling
You can override the default styles by targeting the CSS classes:
.sigma-container {
width: 100%;
height: 100%;
background: #1a1a1a;
canvas {
border-radius: 8px;
}
}🔧 Configuration
Sigma Settings
Configure Sigma.js through the settings prop:
const sigmaSettings = {
defaultNodeColor: '#ec4899',
defaultEdgeColor: '#a1a1aa',
labelColor: '#000000',
labelSize: 12,
defaultNodeSize: 8,
minCameraRatio: 0.1,
maxCameraRatio: 10,
enableEdgeClickEvents: true,
enableEdgeWheelEvents: true,
enableEdgeHoverEvents: true,
};
<SigmaContainer graph={graph} settings={sigmaSettings}>
{/* Your components */}
</SigmaContainer>;Layout Timeout
Configure the layout timeout for automatic layout stopping:
<SigmaContainer
graph={graph}
layoutTimeoutMil={5000} // 5 seconds
>
{/* Your components */}
</SigmaContainer>🧪 Testing
The package is built with testing in mind. Use the provided utilities for testing:
import { render } from '@testing-library/react';
import { SigmaContainer } from 'nx-react-sigma';
import { MultiDirectedGraph } from 'graphology';
const TestComponent = () => {
const graph = new MultiDirectedGraph();
graph.addNode('test', { x: 0, y: 0, size: 10 });
return (
<SigmaContainer graph={graph}>
<div data-testid="graph-content">Graph Content</div>
</SigmaContainer>
);
};
test('renders sigma container', () => {
const { getByTestId } = render(<TestComponent />);
expect(getByTestId('graph-content')).toBeInTheDocument();
});🔄 Migration Guide
From Sigma.js v2 to v3
This package is built for Sigma.js v3. Key changes:
- Updated event handling API
- New renderer architecture
- Improved performance
- Enhanced TypeScript support
🤝 Contributing
This package is part of the nx-platform monorepo. Follow the project's contribution guidelines:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Submit a pull request
Development Setup
# Install dependencies
pnpm install
# Start development mode
pnpm dev
# Run tests
pnpm test
# Build the package
pnpm build
# Lint code
pnpm lint📄 License
ISC License - see the LICENSE file for details.
🙏 Acknowledgments
- Sigma.js - The core graph visualization library
- Graphology - The graph data structure library
- React - The UI library
- TypeScript - For type safety
📞 Support
For questions and support:
- Check the documentation
- Open an issue on GitHub
- Join our community discussions
Built with ❤️ by the nx-platform team
