mirror of
https://github.com/OFFIS-ESC/constellation-analyzer
synced 2026-01-27 07:43:41 +00:00
Implements comprehensive group minimize/maximize functionality and migrates to React Flow v12 (@xyflow/react) with improved edge routing. ## Group Minimize/Maximize Features: - Minimized groups render as compact 220×80px solid rectangles - Original dimensions preserved in metadata and restored on maximize - Child actors hidden (not filtered) to prevent React Flow state issues - Solid color backgrounds (transparency removed for minimized state) - Internal edges filtered out when group is minimized - Dimension sync before minimize ensures correct size on maximize ## Floating Edges: - Dynamic edge routing for connections to/from minimized groups - Edges connect to closest point on minimized group border - Regular actors maintain fixed handle connections - Smooth transitions when toggling group state ## React Flow v12 Migration: - Updated package from 'reactflow' to '@xyflow/react' - Changed imports to named imports (ReactFlow is now named) - Updated CSS imports to '@xyflow/react/dist/style.css' - Fixed NodeProps/EdgeProps to use full Node/Edge types - Added Record<string, unknown> to data interfaces for v12 compatibility - Replaced useStore(state => state.connectionNodeId) with useConnection() - Updated nodeInternals to nodeLookup (renamed in v12) - Fixed event handler types for v12 API changes ## Edge Label Improvements: - Added explicit z-index (1000) to edge labels via EdgeLabelRenderer - Labels now properly render above edge paths ## Type Safety & Code Quality: - Removed all 'any' type assertions in useDocumentHistory - Fixed missing React Hook dependencies - Fixed unused variable warnings - All ESLint checks passing (0 errors, 0 warnings) - TypeScript compilation clean ## Bug Fixes: - Group drag positions now properly persisted to store - Minimized group styling (removed dotted border, padding) - Node visibility using 'hidden' property instead of array filtering - Dimension sync prevents actors from disappearing on maximize 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
137 lines
4 KiB
TypeScript
137 lines
4 KiB
TypeScript
import { Node, Edge } from '@xyflow/react';
|
|
|
|
// Node/Actor Types
|
|
export interface ActorData extends Record<string, unknown> {
|
|
label: string;
|
|
type: string;
|
|
description?: string;
|
|
labels?: string[]; // Array of LabelConfig IDs
|
|
citations?: string[]; // Array of bibliography reference IDs
|
|
metadata?: Record<string, unknown>;
|
|
}
|
|
|
|
export type Actor = Node<ActorData>;
|
|
|
|
// Edge/Relation Types
|
|
export type EdgeDirectionality = 'directed' | 'bidirectional' | 'undirected';
|
|
|
|
export interface RelationData extends Record<string, unknown> {
|
|
label?: string;
|
|
type: string;
|
|
directionality?: EdgeDirectionality;
|
|
strength?: number;
|
|
labels?: string[]; // Array of LabelConfig IDs
|
|
citations?: string[]; // Array of bibliography reference IDs
|
|
metadata?: Record<string, unknown>;
|
|
}
|
|
|
|
export type Relation = Edge<RelationData>;
|
|
|
|
// Node Shape Types
|
|
export type NodeShape =
|
|
| 'rectangle'
|
|
| 'circle'
|
|
| 'roundedRectangle'
|
|
| 'ellipse'
|
|
| 'pill';
|
|
|
|
// Node Type Configuration
|
|
export interface NodeTypeConfig {
|
|
id: string;
|
|
label: string;
|
|
color: string;
|
|
shape: NodeShape;
|
|
icon?: string;
|
|
description?: string;
|
|
}
|
|
|
|
// Edge Type Configuration
|
|
export interface EdgeTypeConfig {
|
|
id: string;
|
|
label: string;
|
|
color: string;
|
|
style?: 'solid' | 'dashed' | 'dotted';
|
|
description?: string;
|
|
defaultDirectionality?: EdgeDirectionality;
|
|
}
|
|
|
|
// Label Configuration
|
|
export type LabelScope = 'actors' | 'relations' | 'both';
|
|
|
|
export interface LabelConfig {
|
|
id: string;
|
|
name: string;
|
|
color: string;
|
|
appliesTo: LabelScope;
|
|
description?: string;
|
|
}
|
|
|
|
// Group Types
|
|
export interface GroupData extends Record<string, unknown> {
|
|
label: string;
|
|
description?: string;
|
|
color: string;
|
|
actorIds: string[];
|
|
minimized?: boolean;
|
|
metadata?: Record<string, unknown>;
|
|
}
|
|
|
|
export type Group = Node<GroupData>;
|
|
|
|
// Graph State
|
|
export interface GraphState {
|
|
nodes: Actor[];
|
|
edges: Relation[];
|
|
groups: Group[];
|
|
nodeTypes: NodeTypeConfig[];
|
|
edgeTypes: EdgeTypeConfig[];
|
|
labels: LabelConfig[];
|
|
}
|
|
|
|
// Editor Settings
|
|
export interface EditorSettings {
|
|
snapToGrid: boolean;
|
|
showGrid: boolean;
|
|
gridSize: number;
|
|
panOnDrag: boolean;
|
|
zoomOnScroll: boolean;
|
|
}
|
|
|
|
// Store Actions
|
|
export interface GraphActions {
|
|
addNode: (node: Actor) => void;
|
|
updateNode: (id: string, updates: Partial<Actor>) => void;
|
|
deleteNode: (id: string) => void;
|
|
addEdge: (edge: Relation) => void;
|
|
updateEdge: (id: string, data: Partial<RelationData>) => void;
|
|
deleteEdge: (id: string) => void;
|
|
addNodeType: (nodeType: NodeTypeConfig) => void;
|
|
updateNodeType: (id: string, updates: Partial<Omit<NodeTypeConfig, 'id'>>) => void;
|
|
deleteNodeType: (id: string) => void;
|
|
addEdgeType: (edgeType: EdgeTypeConfig) => void;
|
|
updateEdgeType: (id: string, updates: Partial<Omit<EdgeTypeConfig, 'id'>>) => void;
|
|
deleteEdgeType: (id: string) => void;
|
|
addLabel: (label: LabelConfig) => void;
|
|
updateLabel: (id: string, updates: Partial<Omit<LabelConfig, 'id'>>) => void;
|
|
deleteLabel: (id: string) => void;
|
|
addGroup: (group: Group) => void;
|
|
updateGroup: (id: string, updates: Partial<GroupData>) => void;
|
|
deleteGroup: (id: string, ungroupActors?: boolean) => void;
|
|
addActorToGroup: (actorId: string, groupId: string) => void;
|
|
removeActorFromGroup: (actorId: string, groupId: string) => void;
|
|
toggleGroupMinimized: (groupId: string) => void;
|
|
clearGraph: () => void;
|
|
setNodes: (nodes: Actor[]) => void;
|
|
setEdges: (edges: Relation[]) => void;
|
|
setGroups: (groups: Group[]) => void;
|
|
setNodeTypes: (nodeTypes: NodeTypeConfig[]) => void;
|
|
setEdgeTypes: (edgeTypes: EdgeTypeConfig[]) => void;
|
|
setLabels: (labels: LabelConfig[]) => void;
|
|
// NOTE: exportToFile and importFromFile have been removed
|
|
// Import/export is now handled by the workspace-level system (workspaceStore)
|
|
loadGraphState: (data: { nodes: Actor[]; edges: Relation[]; groups?: Group[]; nodeTypes: NodeTypeConfig[]; edgeTypes: EdgeTypeConfig[]; labels?: LabelConfig[] }) => void;
|
|
}
|
|
|
|
export interface EditorActions {
|
|
updateSettings: (settings: Partial<EditorSettings>) => void;
|
|
}
|