mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-11-14 09:01:45 +00:00
feat(memory-graph): add onNodeSelect callback for selection changes
Selection lived entirely inside MemoryGraph, so a host embedding the graph had no way to observe which node is selected outside of slideshow mode (onSlideshowNodeChange) or the open-document action (onOpenDocument). That makes common integrations awkward: driving a side panel, syncing selection to the URL, or firing analytics on select. Add an optional onNodeSelect(nodeId) prop that fires whenever the selection changes, regardless of source (click, keyboard navigation, slideshow, or clearing), with null when nothing is selected. It is emitted from an effect keyed on the selection state and reads the callback through a ref, so a changing callback identity does not re-fire it and the selection stays uncontrolled. The initial mount is skipped so a host does not receive a spurious null before any interaction. Purely additive and backward compatible.
This commit is contained in:
parent
3487666481
commit
b569fe2075
3 changed files with 24 additions and 0 deletions
|
|
@ -66,6 +66,7 @@ function App() {
|
|||
| `error` | `Error \| null` | Error to display |
|
||||
| `loadMoreDocuments` | `() => Promise<void>` | 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue