diff --git a/packages/memory-graph/README.md b/packages/memory-graph/README.md index 83710f5a..4ec4db0a 100644 --- a/packages/memory-graph/README.md +++ b/packages/memory-graph/README.md @@ -66,6 +66,7 @@ function App() { | `error` | `Error \| null` | Error to display | | `loadMoreDocuments` | `() => Promise` | Function to load more data | | `highlightDocumentIds` | `string[]` | IDs of documents to highlight | +| `onNodeSelect` | `(nodeId: string \| null) => void` | Called when the selected node changes (click, keyboard, slideshow, or cleared) | ## Documentation diff --git a/packages/memory-graph/src/components/memory-graph.tsx b/packages/memory-graph/src/components/memory-graph.tsx index d165ac71..f0d5e342 100644 --- a/packages/memory-graph/src/components/memory-graph.tsx +++ b/packages/memory-graph/src/components/memory-graph.tsx @@ -39,6 +39,7 @@ export function MemoryGraph({ colors: colorOverrides, totalCount, onOpenDocument, + onNodeSelect, labels: labelOverrides, layering, }: MemoryGraphProps) { @@ -73,6 +74,21 @@ export function MemoryGraph({ // Used as a dependency proxy to recalculate popover positions const [viewportVersion, setViewportVersion] = useState(0) + // Surface selection changes to the host without making selection controlled. + // Keyed on selectedNode only; the callback is read through a ref so a changing + // callback identity does not re-fire it. The initial mount is skipped so a + // host does not receive a spurious null before any interaction. + const onNodeSelectRef = useRef(onNodeSelect) + onNodeSelectRef.current = onNodeSelect + const hasEmittedSelectionRef = useRef(false) + useEffect(() => { + if (!hasEmittedSelectionRef.current) { + hasEmittedSelectionRef.current = true + return + } + onNodeSelectRef.current?.(selectedNode) + }, [selectedNode]) + // Limit documents so total node count (documents + their memories) stays under maxNodes const limitedDocuments = useMemo(() => { if (!maxNodes || documents.length === 0) return documents diff --git a/packages/memory-graph/src/types.ts b/packages/memory-graph/src/types.ts index f871b3da..32bfcaae 100644 --- a/packages/memory-graph/src/types.ts +++ b/packages/memory-graph/src/types.ts @@ -216,6 +216,13 @@ export interface MemoryGraphProps { totalCount?: number /** Callback when user wants to view full document content */ onOpenDocument?: (documentId: string) => void + /** + * Called whenever the selected node changes, by click, keyboard navigation, + * slideshow, or clearing the selection (nodeId is null when nothing is + * selected). Lets a host observe selection without owning the state, e.g. to + * drive a side panel or sync the URL. + */ + onNodeSelect?: (nodeId: string | null) => void /** Custom user-facing labels (partial) - merged with defaults */ labels?: MemoryGraphLabels /** Overlay layering controls */