JavaScript is required

Core Architecture

Purpose and Scope

This document explains the fundamental architecture of the relation-graph system, including its class structure, core design patterns, and component organization. It provides an overview of how the system achieves framework independence while maintaining a unified core logic.

For detailed information about specific aspects:

Architectural Overview

The relation-graph system employs a core-adapter architecture that separates framework-agnostic graph logic from platform-specific UI implementations. This design enables a single codebase to support Vue 2, Vue 3, React, Svelte, and Web Components.

graph TB
    subgraph "Core Layer (Framework Agnostic)"
        CORE["RelationGraphCore
packages/relation-graph-models/models/RelationGraphCore.ts"] DATA_PROV["RGDataProvider
packages/relation-graph-models/data/RGDataProvider.ts"] TYPES["Type System
packages/relation-graph-models/types.ts"] LAYOUTS["Layout Engines
packages/relation-graph-models/layouts/*"] UTILS["Utilities
packages/relation-graph-models/utils/*"] end subgraph "Adapter Layer (Platform Specific)" DP_VUE2["RGDataProvider4Vue2"] DP_VUE3["RGDataProvider4Vue3"] DP_REACT["RGDataProvider4React"] DP_SVELTE["RGDataProvider4Svelte"] end subgraph "UI Layer (Framework Components)" VUE2_UI["Vue 2 Components
packages/platforms/vue2/"] VUE3_UI["Vue 3 Components
packages/platforms/vue3/"] REACT_UI["React Components
packages/platforms/react/"] SVELTE_UI["Svelte Components
packages/platforms/svelte/"] end CORE --> DATA_PROV CORE --> LAYOUTS CORE --> UTILS CORE --> TYPES DATA_PROV -.extends.-> DP_VUE2 DATA_PROV -.extends.-> DP_VUE3 DATA_PROV -.extends.-> DP_REACT DATA_PROV -.extends.-> DP_SVELTE DP_VUE2 --> VUE2_UI DP_VUE3 --> VUE3_UI DP_REACT --> REACT_UI DP_SVELTE --> SVELTE_UI VUE2_UI -.uses.-> CORE VUE3_UI -.uses.-> CORE REACT_UI -.uses.-> CORE SVELTE_UI -.uses.-> CORE

Sources: packages/relation-graph-models/models/RelationGraphCore.ts:1-70, packages/relation-graph-models/models/RelationGraphWith2Data.ts:1-120

Progressive Enhancement Inheritance Pattern

The core system uses a progressive enhancement pattern where RelationGraphCore inherits capabilities through a chain of specialized classes. Each RelationGraphWithX class adds one focused set of capabilities.

graph TB
    RGB["RelationGraphBase
Core utilities, events, UUID generation
packages/.../RelationGraphBase.ts"] RGB --> RGW1["RelationGraphWith1View
DOM coordination, coordinate conversion
packages/.../RelationGraphWith1View.ts"] RGW1 --> RGW2["RelationGraphWith2Data
Reactive data integration
setReactiveData4Vue2/Vue3/React/Svelte
packages/.../RelationGraphWith2Data.ts"] RGW2 --> RGW3O1["RelationGraphWith3Options1Update
Options management, loading states
_updateOptions, setCanvasOffset
packages/.../RelationGraphWith3Options1Update.ts"] RGW3O1 --> RGW3O2["RelationGraphWith3Options2API
Options API, creating line/node state
getCreatingLine, getCreatingNode
packages/.../RelationGraphWith3Options2API.ts"] RGW3O2 --> RGW4["RelationGraphWith4Line
Line path generation
createLineDrawInfo, generateLinePath
packages/.../RelationGraphWith4Line.ts"] RGW4 --> RGW5["RelationGraphWith5Zoom
Zoom operations
zoom, setZoom
packages/.../RelationGraphWith5Zoom.ts"] RGW5 --> RGW6E["RelationGraphWith6Effect
Visual effects, centering
zoomToFit, moveToCenter
packages/.../RelationGraphWith6Effect.ts"] RGW6E --> RGW6L["RelationGraphWith6Layout
Layout algorithms
doLayout, createLayout
packages/.../RelationGraphWith6Layout.ts"] RGW6L --> RGW7["RelationGraphWith7Event
User interactions
onNodeClick, onNodeDragStart
packages/.../RelationGraphWith7Event.ts"] RGW7 --> RGW9["RelationGraphWith9EasyView
Performance mode rendering
updateEasyView, evDrawNode
packages/.../RelationGraphWith9EasyView.ts"] RGW9 --> RGW91["RelationGraphWith91Editing
Node/line editing
setEditingNodes, onResizeStart
packages/.../RelationGraphWith91Editing.ts"] RGW91 --> RGW92["RelationGraphWith92MiniView
Minimap overview
updateMiniView, mvDrawNode
packages/.../RelationGraphWith92MiniView.ts"] RGW92 --> RGW93["RelationGraphWith93Image
Image generation preparation
prepareForImageGeneration
packages/.../RelationGraphWith93Image.ts"] RGW93 --> RGW95["RelationGraphWith95Dom
DOM observers
setDom, initDom
packages/.../RelationGraphWith95Dom.ts"] RGW95 --> RGW99["RelationGraphWith99API
Public API surface
setJsonData, updateNode, getNodes
packages/.../RelationGraphWith99API.ts"] RGW99 --> CORE["RelationGraphCore
Final instance
ready, beforeUnmount
packages/.../RelationGraphCore.ts"] style RGB fill:#f9f9f9 style RGW2 fill:#f9f9f9 style RGW7 fill:#f9f9f9 style CORE fill:#e0e0e0

Capability Layers

Layer Class Primary Responsibility Key Methods
Base RelationGraphBase Event system, UUID generation emitEvent(), generateNewUUID()
View RelationGraphWith1View Coordinate transformations getCanvasXyByViewXy(), getViewXyByCanvasXy()
Data RelationGraphWith2Data Framework reactivity integration setReactiveData4Vue2(), setReactiveData4React()
Options RelationGraphWith3Options1Update Configuration management _updateOptions(), setCheckedNode()
Line Drawing RelationGraphWith4Line Line path computation createLineDrawInfo(), generateLinePath()
Zoom RelationGraphWith5Zoom Zoom operations zoom(), setZoom()
Effects RelationGraphWith6Effect Visual effects zoomToFit(), moveToCenter()
Layout RelationGraphWith6Layout Layout algorithms doLayout(), createLayout()
Events RelationGraphWith7Event User interaction handling onNodeClick(), onNodeDragStart()
Performance RelationGraphWith9EasyView Canvas rendering updateEasyView(), evDrawNode()
Editing RelationGraphWith91Editing Interactive editing setEditingNodes(), onResizeStart()
MiniView RelationGraphWith92MiniView Minimap rendering updateMiniView(), mvDrawNode()
Image RelationGraphWith93Image Image export preparation prepareForImageGeneration()
DOM RelationGraphWith95Dom DOM observation setDom(), initDom()
API RelationGraphWith99API Public API setJsonData(), getGraphJsonData()
Core RelationGraphCore Instance lifecycle ready(), beforeUnmount()

Sources: packages/relation-graph-models/models/RelationGraphBase.ts:1-345, packages/relation-graph-models/models/RelationGraphCore.ts:1-70

Core Components

RelationGraphCore Instance

RelationGraphCore is the central instance that aggregates all capabilities. Each <RelationGraph /> component creates and binds one instance.

graph LR
    subgraph "RelationGraphCore Instance"
        CORE_INST["graphInstance
RelationGraphCore"] subgraph "Internal Components" DP["dataProvider
RGDataProvider"] OPTIONS["options
RGOptionsFull"] LISTENERS["listeners
RGListeners"] EVENT_HANDLERS["eventHandlers
RGEventHandler[]"] end subgraph "DOM References" DOM["$dom
HTMLDivElement"] CANVAS_DOM["$canvasDom
HTMLDivElement"] end end CORE_INST --> DP CORE_INST --> OPTIONS CORE_INST --> LISTENERS CORE_INST --> EVENT_HANDLERS CORE_INST --> DOM CORE_INST --> CANVAS_DOM DP -.references.-> OPTIONS

Key Instance Properties:

Property Type Purpose
dataProvider RGDataProvider Manages graph data, nodes, lines
options RGOptionsFull Configuration state
listeners RGListeners Event handler callbacks
eventHandlers RGEventHandler[] Custom event handlers
$dom HTMLDivElement Root container element
$canvasDom HTMLDivElement Canvas container element
instanceId string Unique instance identifier

Sources: packages/relation-graph-models/models/RelationGraphCore.ts:1-70, packages/relation-graph-models/models/RelationGraphBase.ts:19-31

RGDataProvider System

The RGDataProvider acts as the single source of truth for graph data. Platform-specific data providers extend it to integrate with framework reactivity systems.

graph TB
    subgraph "Base Data Provider"
        BASE["RGDataProvider
Base data management
packages/.../data/RGDataProvider.ts"] BASE_PROPS["Properties:
- graphData: RGGraphData
- options: RGOptionsFull
- commits: DataCommits
- nodeMap: Map
- linkMap: Map"] BASE --> BASE_PROPS end subgraph "Platform Adapters" VUE2_DP["RGDataProvider4Vue2
Vue.set() integration
packages/.../data/RGDataProvider4Vue2.ts"] VUE3_DP["RGDataProvider4Vue3
ref() stores
packages/.../data/RGDataProvider4Vue3.ts"] REACT_DP["RGDataProvider4React
setState() hook
packages/.../data/RGDataProvider4React.ts"] SVELTE_DP["RGDataProvider4Svelte
Svelte stores
packages/.../data/RGDataProvider4Svelte.ts"] end BASE -.extends.-> VUE2_DP BASE -.extends.-> VUE3_DP BASE -.extends.-> REACT_DP BASE -.extends.-> SVELTE_DP VUE2_DP --> VUE2_UPDATE["updateViewHook()
triggers Vue 2 reactivity"] VUE3_DP --> VUE3_UPDATE["updateViewHook()
updates ref() stores"] REACT_DP --> REACT_UPDATE["updateViewHook()
calls setState()"] SVELTE_DP --> SVELTE_UPDATE["updateViewHook()
updates Svelte stores"]

Data Provider Methods:

// Core data access
getNodes(): RGNode[]
getLines(): RGLine[]
getLinks(): RGLink[]
getNodeById(id: string): RGNode | undefined

// Data manipulation
updateNode(nodeId: string, props: Partial<RGNode>): void
updateLine(lineId: string, props: Partial<RGLine>): void
addNodes(nodes: JsonNode[]): void
addLines(lines: JsonLine[]): void
removeNode(nodeId: string): void

// State management
updateOptions(options: Partial<RGOptionsFull>): void
getOptions(): RGOptionsFull
dataUpdated(): void // Triggers view update

Sources: packages/relation-graph-models/models/RelationGraphWith2Data.ts:1-120, packages/relation-graph-models/data/RGDataProvider.ts

Data Flow Architecture

The system implements unidirectional data flow with reactive updates.

graph TB
    subgraph "User Actions"
        USER["User Interactions
Click, Drag, Zoom"] end subgraph "Event Layer" EVENTS["RelationGraphWith7Event
onNodeClick()
onNodeDragStart()
onLineClick()"] end subgraph "Core Instance" CORE["RelationGraphCore
Business Logic"] UPDATE_OPS["Update Operations
updateNode()
updateLine()
updateOptions()"] end subgraph "Data Provider" DP["RGDataProvider
Data Storage"] COMMITS["DataCommits
Change Tracking
- nodesListChanged
- linesListChanged
- changedNodes[]"] end subgraph "Platform Layer" FW_DP["Platform DataProvider
Vue2/Vue3/React/Svelte"] STORES["Reactive Stores
- optionsStore
- nodesStore
- linesStore"] end subgraph "View Layer" COMPONENTS["UI Components
RGCanvas
RGNodePeel
RGLinePath"] DOM["Rendered DOM"] end USER -->|triggers| EVENTS EVENTS -->|calls methods| CORE CORE -->|delegates| UPDATE_OPS UPDATE_OPS -->|modifies| DP DP -->|tracks| COMMITS DP -->|calls updateViewHook| FW_DP FW_DP -->|updates| STORES STORES -.reactive binding.-> COMPONENTS COMPONENTS -->|renders| DOM DOM -.user interaction.-> USER

Commit System

The data provider tracks changes using a commit system to optimize updates:

interface DataCommits {
    nodesListChanged: boolean;      // Full node list changed
    linesListChanged: boolean;      // Full line list changed
    changedNodes: RGNode[];         // Specific modified nodes
    changedLines: RGLine[];         // Specific modified lines
}

Only changed data triggers reactive updates, preventing unnecessary re-renders.

Sources: packages/relation-graph-models/models/RelationGraphWith7Event.ts:1-50, packages/relation-graph-models/data/RGDataProvider.ts

Platform Abstraction Layer

The architecture achieves framework independence through the updateViewHook pattern.

graph LR
    subgraph "Core Logic (Framework Agnostic)"
        CORE_METHOD["Core Method
updateNode()"] DP_UPDATE["RGDataProvider
updateNode()"] end subgraph "Abstraction Point" HOOK["updateViewHook()
Platform-specific implementation"] end subgraph "Vue 2 Implementation" VUE2_IMPL["RGDataProvider4Vue2
Vue.set(node, prop, value)"] end subgraph "Vue 3 Implementation" VUE3_IMPL["RGDataProvider4Vue3
ref.value = newValue"] end subgraph "React Implementation" REACT_IMPL["RGDataProvider4React
setState(newState)"] end subgraph "Svelte Implementation" SVELTE_IMPL["RGDataProvider4Svelte
store.set(newValue)"] end CORE_METHOD --> DP_UPDATE DP_UPDATE --> HOOK HOOK -.implements.-> VUE2_IMPL HOOK -.implements.-> VUE3_IMPL HOOK -.implements.-> REACT_IMPL HOOK -.implements.-> SVELTE_IMPL

Platform-Specific Initialization

Each platform initializes reactivity differently:

Vue 2:

// packages/relation-graph-models/models/RelationGraphWith2Data.ts:31-36
setReactiveData4Vue2(graphData, reactiveOptions, runtimeData, initRawPropertyFn)

Vue 3:

// packages/relation-graph-models/models/RelationGraphWith2Data.ts:44-60
setReactiveData4Vue3(dataStores, graphData, reactiveOptions, runtimeData, initRawPropertyFn)

React:

// packages/relation-graph-models/models/RelationGraphWith2Data.ts:68-78
setReactiveData4React(dataStores, updateViewHook)

Svelte:

// packages/relation-graph-models/models/RelationGraphWith2Data.ts:95-105
setReactiveData4Svelte(dataStores, updaters)

Sources: packages/relation-graph-models/models/RelationGraphWith2Data.ts:1-120

Type System

The type system provides strong contracts across the architecture.

Core Data Types

Type Purpose Location
RGNode Runtime node with layout data packages/relation-graph-models/types.ts:245-275
JsonNode Serializable node packages/relation-graph-models/types.ts:206-241
RGLine Runtime line packages/relation-graph-models/types.ts:355-358
JsonLine Serializable line packages/relation-graph-models/types.ts:295-339
RGLink Line with node references packages/relation-graph-models/types.ts:371-380
RGOptions User configuration packages/relation-graph-models/types.ts:688
RGOptionsFull Complete configuration packages/relation-graph-models/types.ts:641-684
RelationGraphInstance Core instance type packages/relation-graph-models/types.ts:30

Type Relationships

graph TB
    JSON_NODE["JsonNode
User input format
Serializable"] RG_NODE["RGNode
Runtime format
+ lot (layout)
+ rgShouldRender
+ rgCalcedVisibility"] JSON_LINE["JsonLine
User input format
from: string
to: string"] RG_LINE["RGLine
Runtime format
+ id
+ isReverse"] RG_LINK["RGLink
Link object
+ fromNode: RGNode
+ toNode: RGNode
+ line: RGLine"] JSON_NODE -->|json2Node| RG_NODE RG_NODE -->|transNodeToJson| JSON_NODE JSON_LINE -->|json2Line| RG_LINE RG_LINE --> RG_LINK RG_NODE --> RG_LINK

Sources: packages/relation-graph-models/types.ts:1-100

Event System

The event system provides extensibility through a hierarchical event emission model.

graph TB
    subgraph "Event Source"
        USER_ACTION["User Action
e.g., node click"] INTERNAL["Internal Event
e.g., layout finish"] end subgraph "Event Emission (RelationGraphBase)" EMIT["emitEvent(eventName, ...args)"] DEFAULT["defaultEventHandler()
Check listeners property"] CUSTOM["Custom Event Handlers
eventHandlers: RGEventHandler[]"] HOOK["_emitHook
Vue emit integration"] end subgraph "Event Handlers" LISTENER["RGListeners
onNodeClick
onNodeDragStart
onLineClick
etc."] HANDLER["Custom Handlers
addEventHandler(handler)"] end USER_ACTION --> EMIT INTERNAL --> EMIT EMIT --> DEFAULT EMIT --> CUSTOM EMIT --> HOOK DEFAULT --> LISTENER CUSTOM --> HANDLER

Event Types

// packages/relation-graph-models/types.ts
enum RGEventNames {
    onReady = "onReady",
    onNodeClick = "onNodeClick",
    onNodeDragStart = "onNodeDragStart",
    onNodeDragging = "onNodeDragging",
    onNodeDragEnd = "onNodeDragEnd",
    onLineClick = "onLineClick",
    onCanvasClick = "onCanvasClick",
    onNodeExpand = "onNodeExpand",
    onNodeCollapse = "onNodeCollapse",
    onZoomEnd = "onZoomEnd",
    // ... many more
}

Event Emission Flow:

  1. User action triggers event handler method (e.g., onNodeClick())
  2. Method calls emitEvent(RGEventNames.onNodeClick, node, e)
  3. System checks defaultEventHandler() for registered listeners
  4. Calls custom event handlers from eventHandlers array
  5. Invokes _emitHook for framework integration (Vue emit)
  6. Returns custom result if provided, allowing event cancellation

Sources: packages/relation-graph-models/models/RelationGraphBase.ts:110-334, packages/relation-graph-models/types.ts:1000-1100

Key Design Patterns

1. Progressive Enhancement via Inheritance

Each WithX class adds one concern, creating a clear separation of responsibilities. This pattern:

  • Makes the codebase testable (test each layer independently)
  • Enables partial feature adoption
  • Clarifies the dependency chain

2. Core-Adapter Pattern

Framework-agnostic core + platform-specific adapters:

  • RelationGraphCore contains no framework code
  • Platform adapters (RGDataProvider4Vue2, etc.) handle reactivity
  • UI components consume the core instance

3. Data Provider as Single Source of Truth

All data modifications go through RGDataProvider:

  • Centralized state management
  • Change tracking via commits
  • Consistent API across platforms

4. Observer Pattern for DOM Integration

RelationGraphWith95Dom uses browser observers:

  • ResizeObserver for element size changes
  • MutationObserver for DOM mutations
  • Decouples DOM monitoring from business logic

5. Factory Pattern for Layouts

createLayout() instantiates layout algorithms:

  • RGTreeLayout, RGForceLayout, RGCircleLayout, etc.
  • Pluggable layout system
  • Configuration-driven selection

Sources: packages/relation-graph-models/models/RelationGraphWith6Layout.ts:1-50, packages/relation-graph-models/models/RelationGraphWith95Dom.ts:1-100


This architecture enables relation-graph to maintain a single codebase while supporting multiple frameworks, achieving both code reuse and platform-native reactivity patterns. The progressive enhancement pattern keeps complexity manageable as features scale, while the core-adapter pattern ensures clean separation between graph logic and UI integration.