import React, { useState, useMemo } from 'react';
import {
Network,
ZoomIn,
ZoomOut,
RotateCcw,
Search,
SlidersHorizontal,
ChevronRight,
Sparkles,
Link2,
FileText,
Info,
ShieldCheck,
CheckCircle2,
ArrowRight,
ExternalLink,
Layers,
Activity,
GitPullRequest,
BookOpen,
Filter,
Eye,
X,
HelpCircle
} from 'lucide-react';
export default function KnowledgeGraph({ graphData, loading, onSelectTab }) {
const [zoom, setZoom] = useState(1);
const [searchQuery, setSearchQuery] = useState('');
const [selectedNode, setSelectedNode] = useState(null);
const [filterType, setFilterType] = useState('ALL');
const [displayMode, setDisplayMode] = useState('pipeline'); // 'pipeline' (hierarchical flow) | 'network' (constellation)
const [showGraphExplainer, setShowGraphExplainer] = useState(true);
const rawNodes = graphData?.nodes || [];
const rawEdges = graphData?.edges || [];
// Categorize nodes into intuitive medical layers
const categorized = useMemo(() => {
const docs = [];
const claims = [];
const metrics = [];
const rules = [];
const proposals = [];
rawNodes.forEach((n) => {
const t = String(n.type || '').toUpperCase();
if (t === 'DOCUMENT') docs.push(n);
else if (t === 'METRIC') metrics.push(n);
else if (t === 'CLAIM') claims.push(n);
else if (t === 'RULE' || t === 'SAFETY') rules.push(n);
else if (t === 'PROPOSAL') proposals.push(n);
else claims.push(n); // default
});
return { docs, claims, metrics, rules, proposals };
}, [rawNodes]);
// Filter nodes based on user search and category
const filteredNodes = useMemo(() => {
return rawNodes.filter((n) => {
const t = String(n.type || '').toUpperCase();
const matchesType =
filterType === 'ALL' ||
(filterType === 'DOCUMENTS' && t === 'DOCUMENT') ||
(filterType === 'CLAIMS' && t === 'CLAIM') ||
(filterType === 'METRICS' && t === 'METRIC') ||
(filterType === 'RULES' && (t === 'RULE' || t === 'SAFETY')) ||
(filterType === 'PROPOSALS' && t === 'PROPOSAL');
const q = searchQuery.toLowerCase().trim();
const matchesSearch =
!q ||
(n.title || '').toLowerCase().includes(q) ||
String(n.value || '').toLowerCase().includes(q) ||
(n.filename || '').toLowerCase().includes(q);
return matchesType && matchesSearch;
});
}, [rawNodes, filterType, searchQuery]);
// Generate constellation layout coordinates for Network view
const positionedNodes = useMemo(() => {
const total = filteredNodes.length;
if (total === 0) return [];
const centerX = 400;
const centerY = 300;
const radius = Math.min(centerX, centerY) - 70;
return filteredNodes.map((node, i) => {
const angle = (i * 2.399963) % (2 * Math.PI);
const r = 40 + (radius - 40) * Math.sqrt((i + 1) / total);
const x = centerX + r * Math.cos(angle);
const y = centerY + r * Math.sin(angle);
return { ...node, x, y };
});
}, [filteredNodes]);
const nodeMap = useMemo(() => {
const map = {};
positionedNodes.forEach((n) => {
map[n.id] = n;
});
return map;
}, [positionedNodes]);
const getNodeTheme = (type) => {
const t = String(type || '').toUpperCase();
switch (t) {
case 'DOCUMENT':
return {
color: '#3B82F6', // Blue
bg: 'bg-blue-500/10',
border: 'border-blue-500/30',
badge: 'SOURCE DOCUMENT',
icon: FileText,
desc: 'Original medical guideline or clinical PDF.'
};
case 'CLAIM':
return {
color: '#8B5CF6', // Violet
bg: 'bg-violet-500/10',
border: 'border-violet-500/30',
badge: 'CLINICAL ASSERTION',
icon: Activity,
desc: 'Verified clinical finding or standard of care.'
};
case 'METRIC':
return {
color: '#10B981', // Emerald
bg: 'bg-emerald-500/10',
border: 'border-emerald-500/30',
badge: 'DOSING / THRESHOLD',
icon: Sparkles,
desc: 'Quantitative clinical threshold or numerical boundary.'
};
case 'RULE':
case 'SAFETY':
return {
color: '#F59E0B', // Amber
bg: 'bg-amber-500/10',
border: 'border-amber-500/30',
badge: 'SAFETY GUARDRAIL',
icon: ShieldCheck,
desc: 'Quality gate or regulatory constraint (e.g. GCP 24h SLA).'
};
case 'PROPOSAL':
return {
color: '#EC4899', // Pink
bg: 'bg-pink-500/10',
border: 'border-pink-500/30',
badge: 'STAGED PULL REQUEST',
icon: GitPullRequest,
desc: 'Candidate assertion awaiting human peer review.'
};
default:
return {
color: '#06B6D4', // Cyan
bg: 'bg-cyan-500/10',
border: 'border-cyan-500/30',
badge: 'MEDICAL ENTITY',
icon: Link2,
desc: 'Medical concept, drug, or classification.'
};
}
};
if (loading) {
return (
Building Knowledge Lineage Graph...
);
}
return (
{/* =================================================================== */}
{/* 1. PLAIN-ENGLISH EDUCATIONAL BANNER (No Jargon) */}
{/* =================================================================== */}
{showGraphExplainer && (
setShowGraphExplainer(false)}
className="absolute top-3.5 right-3.5 text-slate-500 hover:text-slate-300 transition"
title="Dismiss Explainer"
>
Medical Knowledge Lineage & Connections
Interactive Visual Map
Think of this as a family tree for clinical knowledge . Source medical documents (blue) sit at the root. DiffWeave extracts verified assertions (violet) and dosing cutoffs (emerald), which are automatically guarded by compliance rules (amber).
1. Source Guidelines
→
2. Clinical Findings
→
3. Dosing Thresholds
→
4. Safety Guardrails
)}
{/* =================================================================== */}
{/* 2. GRAPH CONTROLS (Views, Search, Filters) */}
{/* =================================================================== */}
Knowledge Lineage
{rawNodes.length} medical elements • {rawEdges.length} connections
{/* Node Search Bar */}
setSearchQuery(e.target.value)}
className="bg-[#141B2D] border border-slate-800 rounded-lg pl-8 pr-3 py-1.5 text-xs text-slate-200 focus:outline-none focus:ring-1 focus:ring-emerald-500 w-36 sm:w-44"
/>
{/* Category Filter */}
setFilterType(e.target.value)}
className="bg-[#141B2D] border border-slate-800 rounded-lg px-2.5 py-1.5 text-xs text-slate-300 focus:outline-none"
>
All Categories
Source Documents (Blue)
Clinical Assertions (Violet)
Dosing & Metrics (Emerald)
Safety Guardrails (Amber)
Staged PRs (Pink)
{/* View Mode Toggle: Lineage Pipeline vs Network Constellation */}
setDisplayMode('pipeline')}
className={`px-2.5 py-1 rounded text-xs font-semibold transition flex items-center space-x-1.5 ${
displayMode === 'pipeline' ? 'bg-slate-700 text-white' : 'text-slate-400 hover:text-white'
}`}
title="Pipeline Flow: Left-to-right lineage tree"
>
Pipeline Flow
setDisplayMode('network')}
className={`px-2.5 py-1 rounded text-xs font-semibold transition flex items-center space-x-1.5 ${
displayMode === 'network' ? 'bg-slate-700 text-white' : 'text-slate-400 hover:text-white'
}`}
title="Network Constellation: Cluster canvas"
>
Constellation
{/* Zoom Controls (Network Mode Only) */}
{displayMode === 'network' && (
setZoom((z) => Math.min(z + 0.15, 2.0))}
className="p-1.5 hover:text-white text-slate-400 transition"
title="Zoom In"
>
setZoom((z) => Math.max(z - 0.15, 0.6))}
className="p-1.5 hover:text-white text-slate-400 transition"
title="Zoom Out"
>
setZoom(1)}
className="p-1.5 hover:text-white text-slate-400 transition"
title="Reset Zoom"
>
)}
{/* =================================================================== */}
{/* 3. MAIN VISUAL CANVAS: PIPELINE FLOW vs CONSTELLATION */}
{/* =================================================================== */}
{displayMode === 'pipeline' ? (
/* ================================================================= */
/* VIEW 1: STRUCTURED PIPELINE LINEAGE FLOW (No Jargon, Easy to Get) */
/* ================================================================= */
{/* Column 1: Source Medical Documents */}
Source Documents
{categorized.docs.length || 1}
Baseline protocols uploaded to DiffWeave staging.
{(categorized.docs.length > 0 ? categorized.docs : [
{ id: 'doc-baseline', title: 'Clinical-Guidelines-2026.pdf', value: 'Master clinical protocol version 2026', type: 'DOCUMENT' }
]).map((doc) => (
setSelectedNode(doc)}
className="p-3 rounded-xl bg-[#101726] hover:bg-[#162136] border border-blue-500/30 transition cursor-pointer space-y-1.5 shadow-sm group"
>
{doc.title}
PDF
{doc.value || 'Verified baseline source document'}
))}
{/* Column 2: Clinical Findings & Guidelines */}
{categorized.claims.length}
Clinical claims extracted and committed to master.
{categorized.claims.map((claim) => (
setSelectedNode(claim)}
className="p-3 rounded-xl bg-[#121426] hover:bg-[#1A1C38] border border-violet-500/30 transition cursor-pointer space-y-1.5 shadow-sm group"
>
{claim.title}
96% Conf
{claim.value}
))}
{/* Column 3: Dosing & Numerical Thresholds */}
Dosing & Thresholds
{categorized.metrics.length}
Quantitative boundaries and numerical guidelines.
{categorized.metrics.map((metric) => (
setSelectedNode(metric)}
className="p-3 rounded-xl bg-[#0F1A1C] hover:bg-[#152528] border border-emerald-500/30 transition cursor-pointer space-y-1.5 shadow-sm group"
>
{metric.title}
{Math.round((metric.confidence || 0.95) * 100)}%
{metric.value}
))}
{/* Column 4: Safety Guardrails & Compliance Rules */}
Automated policy checks enforcing clinical compliance.
{[
{ id: 'rule-floor', title: 'Confidence Floor ≥ 85%', value: 'Prevents low-confidence extractions from polluting the Truth Register.', type: 'RULE' },
{ id: 'rule-provenance', title: 'Mandatory Provenance Citation', value: 'Requires every claim to cite exact document page and paragraph.', type: 'RULE' },
{ id: 'rule-sae', title: 'Safety Escalation SLA (24h)', value: 'Strict 24-hour reporting deadline for adverse clinical deviations.', type: 'RULE' },
{ id: 'rule-stats', title: 'Statistical p-Value Validation', value: 'Ensures clinical numerical claims specify confidence intervals.', type: 'RULE' },
].map((rule) => (
setSelectedNode(rule)}
className="p-3 rounded-xl bg-[#1A160F] hover:bg-[#262016] border border-amber-500/30 transition cursor-pointer space-y-1.5 shadow-sm group"
>
{rule.title}
{rule.value}
))}
) : (
/* ================================================================= */
/* VIEW 2: INTERACTIVE NETWORK CONSTELLATION CANVAS */
/* ================================================================= */
{/* Connecting Lines */}
{rawEdges.map((edge, idx) => {
const src = nodeMap[edge.source];
const tgt = nodeMap[edge.target];
if (!src || !tgt) return null;
const isHighlighted = selectedNode && (selectedNode.id === src.id || selectedNode.id === tgt.id);
return (
);
})}
{/* Circular Nodes */}
{positionedNodes.map((node) => {
const isSelected = selectedNode?.id === node.id;
const theme = getNodeTheme(node.type);
return (
setSelectedNode(node)}
className="cursor-pointer group"
>
{isSelected && (
)}
{node.title.length > 20 ? node.title.slice(0, 18) + '...' : node.title}
);
})}
{/* Side Inspector in Constellation Mode */}
Element Inspector
{selectedNode ? (
renderNodeDetails(selectedNode)
) : (
Click any node on the graph to inspect its clinical finding, confidence, and source document.
)}
)}
{/* =================================================================== */}
{/* 4. SLIDE-OVER / MODAL INSPECTOR WHEN CLICKING ANY NODE IN PIPELINE */}
{/* =================================================================== */}
{selectedNode && displayMode === 'pipeline' && (
setSelectedNode(null)}
/>
{getNodeTheme(selectedNode.type).badge}
{selectedNode.title}
setSelectedNode(null)}
className="p-1 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-400 hover:text-white transition"
>
{renderNodeDetails(selectedNode)}
setSelectedNode(null)}
className="px-4 py-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-300 font-semibold text-xs transition"
>
Close
{onSelectTab && selectedNode.type !== 'RULE' && (
{
setSelectedNode(null);
onSelectTab('knowledge');
}}
className="px-4 py-2 rounded-xl bg-emerald-600 hover:bg-emerald-500 text-white font-semibold text-xs transition flex items-center space-x-1.5 shadow-lg shadow-emerald-500/20"
>
View in Truth Register
)}
)}
);
// Helper function to render node detail card
function renderNodeDetails(node) {
const theme = getNodeTheme(node.type);
const Icon = theme.icon;
return (
{theme.badge}
{node.value || node.title}
{theme.desc}
{/* Provenance & Citation */}
Provenance Citation
Source Protocol:
{node.filename || 'Clinical_Guideline.pdf'}
Section Citation:
Section 2.1 Baseline Standard
{node.confidence !== undefined && (
Confidence Score:
{Math.round((node.confidence || 0.95) * 100)}% Verified
)}
{/* Connected Elements */}
Lineage Relationships
Extracted from: {node.filename || 'Clinical_Guideline.pdf'}
Guarded by: Confidence Floor (≥85%) & Mandatory Provenance
Committed branch: refs/heads/main
);
}
}