Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@gravity-ui/graph

gravity-ui1.5kMIT1.0.0TypeScript support: included

Modern graph editor component

gravity-ui, graph, graph-editor, flowchart, workflow, node-based, node-editor, block-diagram, data-visualization, canvas, diagram

readme

@gravity-ui/graph · npm package Release storybook

A graph visualization library that combines the best of both worlds:

  • Canvas for high performance when viewing the full graph
  • HTML/React for rich interactions when zoomed in

No more choosing between performance and interactivity. Perfect for large diagrams, flowcharts, and node-based editors.

Motivation

Modern web applications often require complex visualization and interactivity, but existing solutions typically focus on a single rendering technology:

  • Canvas offers high performance for complex graphics but is limited in text handling and interactivity.
  • HTML DOM is convenient for interfaces but less efficient for complex graphics or large numbers of elements.

@gravity-ui/graph solves this by automatically switching between Canvas and HTML based on zoom level:

  • Zoomed Out: Uses Canvas for efficient rendering of the full graph
  • Medium Zoom: Shows schematic view with basic interactivity
  • Zoomed In: Switches to HTML/React components for rich interactions

How It Works

The library uses a smart rendering system that automatically manages the transition between Canvas and React components:

  1. At low zoom levels, everything is rendered on Canvas for performance
  2. When zooming in to detailed view, the GraphCanvas component:
    • Tracks camera viewport and scale changes
    • Calculates which blocks are visible in the current viewport (with padding for smooth scrolling)
    • Renders React components only for visible blocks
    • Automatically updates the list when scrolling or zooming
    • Removes React components when zooming out
// Example of React components rendering
const MyGraph = () => {
  return (
    <GraphCanvas
      graph={graph}
      renderBlock={(graph, block) => (
        <MyCustomBlockComponent 
          graph={graph} 
          block={block}
        />
      )}
    />
  );
};

Storybook

Install

npm install @gravity-ui/graph

Examples

React Example

Detailed React Components Documentation

import { EAnchorType, Graph } from "@gravity-ui/graph";
import { GraphCanvas, GraphState, GraphBlock, useGraph } from "@gravity-ui/graph/react";
import React from "react";

const config = {};

export function GraphEditor() {
  const { graph, setEntities, start } = useGraph(config);

  useEffect(() => {
    setEntities({
      blocks: [
        {
          is: "block-action",
          id: "action_1",
          x: -100,
          y: -450,
          width: 126,
          height: 126,
          selected: true,
          name: "Block #1",
          anchors: [
            {
              id: "out1",
              blockId: "action_1",
              type: EAnchorType.OUT,
              index: 0
            }
          ],
        },
        {
          id: "action_2",
          is: "block-action",
          x: 253,
          y: 176,
          width: 126,
          height: 126,
          selected: false,
          name: "Block #2",
          anchors: [
            {
              id: "in1",
              blockId: "action_2",
              type: EAnchorType.IN,
              index: 0
            }
          ],
        }
      ],
      connections: [
        {
          sourceBlockId: "action_1",
          sourceAnchorId: "out1",
          targetBlockId: "action_2",
          targetAnchorId: "in1",
        }
      ]
    });
  }, [setEntities]);

  const renderBlockFn = (graph, block) => {
    return <GraphBlock graph={graph} block={block}>{block.id}</GraphBlock>;
  };

  return (
    <GraphCanvas
      graph={graph}
      renderBlock={renderBlockFn}
      onStateChanged={({ state }) => {
        if (state === GraphState.ATTACHED) {
          start();
          graph.zoomTo("center", { padding: 300 });
        }
      }}
    />
  );
}

Vanilla JavaScript Example

import { Graph } from "@gravity-ui/graph";

// Create container element
const container = document.createElement('div');
container.style.width = '100vw';
container.style.height = '100vh';
container.style.overflow = 'hidden';
document.body.appendChild(container);

// Initialize graph with configuration
const graph = new Graph({
    configurationName: "example",
    blocks: [],
    connections: [],
    settings: {
        canDragCamera: true,
        canZoomCamera: true,
        useBezierConnections: true,
        showConnectionArrows: true
    }
}, container);

// Add blocks and connections
graph.setEntities({
    blocks: [
        {
            is: "block-action",
            id: "block1",
            x: 100,
            y: 100,
            width: 120,
            height: 120,
            name: "Block #1",
            anchors: [
                {
                    id: "out1",
                    blockId: "block1",
                    type: EAnchorType.OUT,
                    index: 0
                }
            ]
        },
        {
            is: "block-action",
            id: "block2",
            x: 300,
            y: 300,
            width: 120,
            height: 120,
            name: "Block #2",
            anchors: [
                {
                    id: "in1",
                    blockId: "block2",
                    type: EAnchorType.IN,
                    index: 0
                }
            ]
        }
    ],
    connections: [
        {
            sourceBlockId: "block1",
            sourceAnchorId: "out1",
            targetBlockId: "block2",
            targetAnchorId: "in1"
        }
    ]
});

// Start rendering
graph.start();

// Center the view
graph.zoomTo("center", { padding: 100 });

Live Examples

Documentation

Table of Contents

  1. System

  2. Components

  3. Rendering

  4. Blocks and Connections

changelog

Changelog

1.0.0 (2025-06-20)

⚠ BREAKING CHANGES

  • React components moved to separate module

chore

refactor

  • separate React dependencies from core library (#74) (12648c4)

0.5.0 (2025-06-19)

Features

  • add double-click event support for graph components (#92) (df6ed69)

Bug Fixes

  • update anchors before geometry to fix React positioning (#98) (59700fa)

0.4.3 (2025-05-14)

Bug Fixes

  • layers: set attached flag on start to enable proper detach/remount (#82) (a01be39)
  • story: always deep-clone state on export to prevent frozen/proxied object errors (#87) (a936de5)

0.4.2 (2025-04-28)

Bug Fixes

  • Layer: streamline context setting in afterInit and createCanvas methods (a7b93e3)

0.4.1 (2025-04-28)

Bug Fixes

  • package.json: update copy-styles command to use quotes for path consistency (#76) (172254a)

0.4.0 (2025-04-27)

Features

  • add useLayer hook for managing graph layers and enhance documentation (c7e083f)
  • Camera: add methods for converting relative coordinates to absolute screen space (84a8111)
  • DevTools: introduce DevToolsLayer for enhanced graph debugging and measurement (d450e12)
  • export useLayer hook from index file to enhance layer management (43d4e9c)
  • Layers: add an AbortController to manage events (#64) (714fb0e)
  • NewBlockLayer, ConnectionLayer: added validation and duplication of blocks by a group (#62) (4df468d)

Bug Fixes

  • Events: remove mousemove event from API/docs: it was never actually dispatched (8393772)
  • Group: stop click event propagation to prevent selection reset (#65) (7b438de)
  • Improve block signal handling and add $blocksReactiveState for full state tracking (48c78aa)
  • make showConnectionArrows setting properly control arrow visibility (#67) (8139e37)

0.3.1 (2025-03-19)

chore

Features

  • canvas: allow customize below layer (#56) (8b20838)

Bug Fixes

  • delayed anchor render on html layer (#54) (da92917)
  • Delegate pointer-events from the BlockGroupLayer to the Camera on interact with groups (#57) (450475b)
  • improve anchors props type (#52) (0553bfa)

0.3.0 (2025-03-05)

Features

0.2.1 (2025-01-31)

Bug Fixes

  • unselect entities without meta key pressed (#42) (fc670dc)

0.2.0 (2025-01-14)

Features

Bug Fixes

0.1.2 (2024-12-18)

Bug Fixes

  • update snapshots on release on CI (#34) (e5c0daa)

0.1.1 (2024-12-18)

chore

0.1.0 (2024-12-18)

Features

  • Allow to customization the connections (#29) (fe4fb33)

0.0.6 (2024-12-03)

chore

Features

  • add connection label inner paddings (#27) (a6791e0)

0.0.5 (2024-11-29)

chore

0.0.4 (2024-11-26)

chore

Features

  • anchor: add selected field for anchor selection change event (49b9c10)

Bug Fixes

  • update css after call setEntities (a38b363)

0.0.3 (2024-10-22)

chore

Features

  • TConnection: add id field (3e5b9a7)

Bug Fixes

  • selection: stop emit unselect event if select field not specified (8642d3b)
  • useBlockAnchorState: fix no blockState when graph entities updated (4fbdc37)

0.0.2 (2024-10-17)

chore

Features

Bug Fixes

  • Camera: fix block event propagation (0b9ca02)
  • LayersService: disconnect resizeObserver when the service is detached (bcabe44)
  • Minimap: fix crashes when block has no viewComponent (78e3186)