# React Components API
## Import Structure
The library separates core functionality from React components:
```typescript
// Core functionality (no React dependency)
import { Graph } from "@gravity-ui/graph";
// React components (requires React)
import { GraphCanvas, GraphBlock, GraphBlockAnchor, useGraph, useGraphEvent } from "@gravity-ui/graph/react";
```
## Architecture
The library uses a modular architecture that separates the core rendering engine from React-specific implementations:
- **Core Layer**: Handles canvas rendering, event management, and data structures
- **GraphCanvas**: A React component that creates and manages the ReactLayer
This separation allows the core library to be framework-agnostic while providing seamless React integration.
## Key Components
### GraphCanvas
The main container component that renders your graph:
```tsx
import { GraphCanvas } from "@gravity-ui/graph/react";
```
#### Props
- **`graph`** (required): The Graph instance to render
- **`renderBlock`** (optional): Function to render custom block components
- **`className`** (optional): CSS class for the main container
- **`blockListClassName`** (optional): CSS class applied to the blocks container layer
- **`reactLayerRef`** (optional): Ref to access the ReactLayer instance directly
- **Event callbacks**: All graph event callbacks can be passed as props
### GraphBlock
The `GraphBlock` component is a crucial wrapper that handles the complex interaction between HTML elements and the canvas layer. It's responsible for:
1. **Position Synchronization**: Automatically aligns HTML content with canvas coordinates
2. **State Management**: Handles selection, hover states, and drag interactions
3. **Layout Management**: Maintains proper block dimensions and positioning
4. **Z-index Handling**: Manages proper layering of blocks
5. **CSS Variables**: Injects position and state variables for styling
```tsx
import { GraphBlock } from "@gravity-ui/graph/react";
Your block content here
```
The component automatically inherits styles from graph settings but can be customized using CSS variables:
```css
.custom-block {
/* Position variables (automatically set by GraphBlock) */
--graph-block-geometry-x: 0px;
--graph-block-geometry-y: 0px;
--graph-block-geometry-width: 200px;
--graph-block-geometry-height: 100px;
--graph-block-z-index: 1;
--graph-block-order: 0;
/* Theme variables (from graph settings) */
--graph-block-bg: rgba(37, 27, 37, 1);
--graph-block-border: rgba(229, 229, 229, 0.2);
--graph-block-border-selected: rgba(255, 190, 92, 1);
/* Custom styling */
background-color: var(--graph-block-bg);
border: 1px solid var(--graph-block-border);
}
.custom-block.selected {
border-color: var(--graph-block-border-selected);
}
```
### GraphBlockAnchor
Renders connection points on blocks. The component supports two positioning modes:
1. **fixed** - Anchors are placed at exact coordinates relative to the block:
```tsx
import { GraphBlockAnchor } from "@gravity-ui/graph/react";
{(state) => (
{/* Anchor visuals */}
)}
```
2. **auto** - Anchors are automatically positioned based on their type:
```tsx
{(state) => (
{/* Anchor visuals */}
)}
```
Anchor styling also uses CSS variables:
```css
.anchor {
--graph-block-anchor-bg: rgba(255, 190, 92, 1);
--graph-block-anchor-border-selected: rgba(255, 190, 92, 1);
}
```
## React Hooks
The library provides a comprehensive set of React hooks for working with the graph:
| Hook | Description |
|------|-------------|
| `useGraph` | Create and manage a Graph instance |
| `useGraphEvent` | Subscribe to a single graph event |
| `useGraphEvents` | Subscribe to multiple graph events |
| `useLayer` | Add and manage layers |
| `useBlockState` | Subscribe to block state changes |
| `useBlockViewState` | Get block view component |
| `useBlockAnchorState` | Subscribe to anchor state changes |
| `useSignal` | Subscribe to signal values |
| `useComputedSignal` | Create computed signals |
| `useSignalEffect` | Run effects on signal changes |
| `useSchedulerDebounce` | Create debounced function with frame timing |
| `useSchedulerThrottle` | Create throttled function with frame timing |
| `useScheduledTask` | Schedule task for frame-based execution |
| `useSceneChange` | React to scene updates (camera, viewport) |
For detailed documentation of all hooks, see [React Hooks Reference](hooks.md).
### Quick Example
```tsx
import { useGraph, useGraphEvent, useBlockState } from '@gravity-ui/graph/react';
function MyGraph() {
const { graph, setEntities, start } = useGraph({
settings: { canDragBlocks: true },
});
// Subscribe to events
useGraphEvent(graph, "block-change", ({ block }) => {
console.log("Block changed:", block);
});
// Track block state
const blockState = useBlockState(graph, "block-1");
return ;
}
```
## Graph Configuration
The graph can be extensively configured through the `useGraph` hook. See the [full configuration reference](https://gravity-ui.com/components/graph) for details.
## Declarative Components
In addition to the imperative `useLayer` hook, the library provides declarative React components for working with layers and HTML overlays.
### GraphLayer
The `GraphLayer` component provides a declarative way to add existing Layer classes to the graph:
```tsx
import { GraphLayer, GraphCanvas, useGraph } from '@gravity-ui/graph/react';
import { DevToolsLayer } from '@gravity-ui/graph/plugins';
function MyGraph() {
const { graph, setEntities, start } = useGraph({});
React.useEffect(() => {
if (graph) {
setEntities({ blocks: [...], connections: [...] });
start();
}
}, [graph]);
return (
);
}
```
### GraphPortal
The `GraphPortal` component allows creating HTML layers without writing separate Layer classes:
```tsx
import { GraphPortal, GraphCanvas, useGraph } from '@gravity-ui/graph/react';
function MyGraph() {
const { graph, setEntities, start } = useGraph({});
const [counter, setCounter] = useState(0);
React.useEffect(() => {
if (graph) {
setEntities({ blocks: [...], connections: [...] });
start();
}
}, [graph]);
return (
Custom UI
);
}
```
For more detailed information about declarative components, see the [dedicated documentation](declarative-components.md).
### View Configuration
```tsx
const config = {
viewConfiguration: {
colors: {
block: {
background: "rgba(37, 27, 37, 1)",
border: "rgba(229, 229, 229, 0.2)",
selectedBorder: "rgba(255, 190, 92, 1)"
},
connection: {
background: "rgba(255, 255, 255, 0.5)",
selectedBackground: "rgba(234, 201, 74, 1)"
},
anchor: {
background: "rgba(255, 190, 92, 1)"
},
canvas: {
layerBackground: "rgba(22, 13, 27, 1)",
dots: "rgba(255, 255, 255, 0.2)"
}
},
constants: {
block: {
SCALES: [0.1, 0.2, 0.5], // Zoom levels for block rendering
}
}
}
};
```
### Behavior Settings
```tsx
const config = {
settings: {
// Camera controls
canDragCamera: true,
canZoomCamera: true,
// Block interactions
canDragBlocks: true,
canDuplicateBlocks: false,
canChangeBlockGeometry: 'ALL', // 'NONE' | 'ALL' | 'SELECTED'
// Connection settings
canCreateNewConnections: true,
showConnectionArrows: true,
useBezierConnections: true,
// Visual settings
scaleFontSize: 1,
useBlocksAnchors: true,
showConnectionLabels: false,
// Custom block components
blockComponents: {
'action-block': ActionBlockComponent,
'text-block': TextBlockComponent
}
}
};
```
## Event Handling
The library provides a rich set of events you can listen to:
```tsx
import { useGraphEvent } from '@gravity-ui/graph/react';
// When a new connection is created
useGraphEvent(graph, "connection-created",
({ sourceBlockId, targetBlockId }, event) => {
// Handle new connection
// Use event.preventDefault() to cancel if needed
});
// When blocks are selected
useGraphEvent(graph, "blocks-selection-change",
({ changes }) => {
console.log('Added:', changes.add);
console.log('Removed:', changes.removed);
});
// When a block is modified
useGraphEvent(graph, "block-change",
({ block }) => {
// Handle block changes
});
```
## Common Patterns
### Zooming to Content
```tsx
// Zoom to center with padding
graph.zoomTo("center", { padding: 300 });
// Zoom to specific blocks
graph.zoomTo([blockId1, blockId2], {
transition: 250
});
```
### Managing Selection
```tsx
useGraphEvent(graph, "blocks-selection-change",
({ changes }) => {
const selectedBlocks = changes.add.map(id =>
graph.rootStore.blocksList.getBlock(id)
);
// Update your UI with selected blocks
});
```
### Custom Connection Logic
```tsx
useGraphEvent(graph, "connection-created",
(connection, event) => {
event.preventDefault(); // Prevent default connection
// Apply your own connection logic
if (validateConnection(connection)) {
graph.api.addConnection({
...connection,
// Add custom properties
});
}
});
```
## Complete Example
Here's a practical example that demonstrates the core features:
```tsx
import React, { useCallback } from 'react';
import { Graph } from '@gravity-ui/graph';
import { GraphCanvas, GraphBlock, GraphBlockAnchor, useGraph, useGraphEvent, TBlock } from '@gravity-ui/graph/react';
function BlockComponent({ block, graph }: { block: TBlock; graph: Graph }) {
return (
{/* Block content */}