Documentation/Advanced Usage

Advanced Usage

This guide covers advanced usage patterns and techniques for Diagrammatic-UI, focusing on data adapters and integrations with other libraries.

Data Adapters

Diagrammatic-UI includes adapters for converting between different graph data formats. These adapters help you integrate with various data sources.

AdapterPurposeInput FormatOutput Format
D3ForceAdapterD3.js force layout compatibilityD3 force simulation dataDigrammatic UI format
CytoscapeAdapterCytoscape.js compatibilityCytoscape.js elementsDigrammatic UI format
AdjacencyMatrixAdapterMatrix representationAdjacency matrixDigrammatic UI format
DependencyTreeAdapterHierarchical tree structuresDependency treeDigrammatic UI format
JSONGraphAdapterStandard JSON graph formatsJSON Graph FormatDigrammatic UI format

Using Adapters

Direct Import

You can import adapters directly:

import { D3ForceAdapter, CytoscapeAdapter } from 'diagrammatic-ui';

// Create an adapter instance
const d3Adapter = new D3ForceAdapter();

// Convert from D3 format to Digrammatic UI format
const d3Data = {
  nodes: [
    { id: "1", name: "Node 1" },
    { id: "2", name: "Node 2" }
  ],
  links: [
    { source: "1", target: "2" }
  ]
};

const graphData = d3Adapter.toGraph(d3Data);

// Use the converted data
<Graph data={graphData} />

// Convert back to D3 format
const convertedD3Data = d3Adapter.fromGraph(graphData);

Using Helper Functions

For convenience, the library provides helper functions:

import { 
  convertFromD3, 
  convertToD3,
  convertFromCytoscape,
  convertToCytoscape 
} from 'diagrammatic-ui';

// Convert from D3 format
const graphData = convertFromD3(d3Data);

// Convert to Cytoscape format
const cytoscapeData = convertToCytoscape(graphData);

Using the Adapter Factory

For dynamic adapter selection:

import { AdapterFactory, DataFormatType } from 'diagrammatic-ui';

function convertData(data: any, format: DataFormatType) {
  return AdapterFactory.toGraph(data, format);
}

// Usage
const graphData = convertData(sourceData, 'cytoscape');

Adapter Details

D3ForceAdapter

Converts between D3.js force simulation data and Digrammatic UI format.

D3 Format

interface D3ForceData {
  nodes: Array<{
    id: string;
    name?: string;
    [key: string]: any;
  }>;
  links: Array<{
    source: string;
    target: string;
    [key: string]: any;
  }>;
}

Example

import { D3ForceAdapter } from 'diagrammatic-ui';

const d3Data = {
  nodes: [
    { id: "1", name: "Node 1", group: 1 },
    { id: "2", name: "Node 2", group: 2 }
  ],
  links: [
    { source: "1", target: "2", value: 1 }
  ]
};

const adapter = new D3ForceAdapter();
const graphData = adapter.toGraph(d3Data);

CytoscapeAdapter

Converts between Cytoscape.js elements and Digrammatic UI format.

Cytoscape Format

interface CytoscapeData {
  elements: {
    nodes: Array<{
      data: {
        id: string;
        label?: string;
        [key: string]: any;
      };
      position?: { x: number; y: number };
      [key: string]: any;
    }>;
    edges: Array<{
      data: {
        id: string;
        source: string;
        target: string;
        [key: string]: any;
      };
      [key: string]: any;
    }>;
  };
}

Example

import { CytoscapeAdapter } from 'diagrammatic-ui';

const cytoscapeData = {
  elements: {
    nodes: [
      { data: { id: '1', label: 'Node 1' }, position: { x: 100, y: 100 } },
      { data: { id: '2', label: 'Node 2' }, position: { x: 200, y: 200 } }
    ],
    edges: [
      { data: { id: 'e1', source: '1', target: '2', label: 'connects to' } }
    ]
  }
};

const adapter = new CytoscapeAdapter();
const graphData = adapter.toGraph(cytoscapeData);

Dynamic Graph Updates

Handle dynamic updates to the graph data:

import React, { useState, useEffect } from 'react';
import { Graph, GraphData } from 'diagrammatic-ui';

const DynamicGraph = () => {
  const [graphData, setGraphData] = useState<GraphData>({
    nodes: [],
    edges: []
  });
  
  // Simulate data loading or real-time updates
  useEffect(() => {
    // Initial data load
    fetchGraphData().then(data => {
      setGraphData(data);
    });
    
    // Set up subscription for real-time updates
    const subscription = subscribeToUpdates(update => {
      setGraphData(prevData => {
        // Handle different update types
        switch (update.type) {
          case 'ADD_NODE':
            return {
              ...prevData,
              nodes: [...prevData.nodes, update.node]
            };
            
          case 'REMOVE_NODE':
            return {
              ...prevData,
              nodes: prevData.nodes.filter(n => n.id !== update.nodeId),
              // Also remove any edges connected to this node
              edges: prevData.edges.filter(
                e => e.source !== update.nodeId && e.target !== update.nodeId
              )
            };
            
          case 'ADD_EDGE':
            return {
              ...prevData,
              edges: [...prevData.edges, update.edge]
            };
            
          case 'UPDATE_NODE':
            return {
              ...prevData,
              nodes: prevData.nodes.map(n => 
                n.id === update.nodeId ? { ...n, ...update.changes } : n
              )
            };
            
          default:
            return prevData;
        }
      });
    });
    
    // Clean up subscription
    return () => {
      subscription.unsubscribe();
    };
  }, []);
  
  return (
    <Graph
      data={graphData}
      autoLayout="force"
      layoutOptions={{
        // Use incremental layout for better performance with dynamic updates
        incremental: true,
        // Reduce animation time for quicker updates
        animationDuration: 300
      }}
    />
  );
};