mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-09-16 23:41:12 +00:00
Package changes (packages/memory-graph): - Spatial grid nearest-neighbor: O(n^2) -> O(n*k) for doc-doc edge rendering - Zoom-based edge culling: skip low-similarity edges at low zoom levels - Modular canvas engine from mono repo (renderer, simulation, viewport, hit-test) - Remove vanilla-extract CSS, use inline styles only - Add motion/react for slide-in animations - Export mock data generator for stress testing - Add performance and integration tests (15/15 pass) Web app changes (apps/web): - Remove local graph implementation (~4400 lines deleted) - Add thin wrapper (memory-graph-wrapper.tsx) using useGraphApi hook - Keep app-specific graph-card.tsx and use-graph-api.ts Playground changes (apps/memory-graph-playground): - Add stress test buttons (50/100/200/500 docs) - Add mock data generation via package - Convert DocumentWithMemories to GraphApiDocument format - Show FPS counter during stress tests All TypeScript compiles clean. Performance tests: 15/15 pass.
78 lines
2 KiB
TypeScript
78 lines
2 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useRef, useState } from "react"
|
|
import { MemoryGraph as MemoryGraphBase } from "@supermemory/memory-graph"
|
|
import type { GraphApiDocument, GraphApiEdge } from "@supermemory/memory-graph"
|
|
import { useGraphApi } from "./hooks/use-graph-api"
|
|
|
|
export interface MemoryGraphWrapperProps {
|
|
children?: React.ReactNode
|
|
isLoading?: boolean
|
|
error?: Error | null
|
|
variant?: "console" | "consumer"
|
|
legendId?: string
|
|
highlightDocumentIds?: string[]
|
|
highlightsVisible?: boolean
|
|
containerTags?: string[]
|
|
documentIds?: string[]
|
|
maxNodes?: number
|
|
isSlideshowActive?: boolean
|
|
onSlideshowNodeChange?: (nodeId: string | null) => void
|
|
onSlideshowStop?: () => void
|
|
canvasRef?: React.RefObject<HTMLCanvasElement | null>
|
|
}
|
|
|
|
export function MemoryGraph({
|
|
children,
|
|
isLoading: externalIsLoading = false,
|
|
error: externalError = null,
|
|
variant = "console",
|
|
containerTags,
|
|
documentIds,
|
|
maxNodes = 200,
|
|
canvasRef,
|
|
...rest
|
|
}: MemoryGraphWrapperProps) {
|
|
const [containerSize, setContainerSize] = useState({ width: 0, height: 0 })
|
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
|
|
useEffect(() => {
|
|
const el = containerRef.current
|
|
if (!el) return
|
|
const ro = new ResizeObserver(() => {
|
|
setContainerSize({ width: el.clientWidth, height: el.clientHeight })
|
|
})
|
|
ro.observe(el)
|
|
setContainerSize({ width: el.clientWidth, height: el.clientHeight })
|
|
return () => ro.disconnect()
|
|
}, [])
|
|
|
|
const {
|
|
data: apiData,
|
|
isLoading: apiIsLoading,
|
|
error: apiError,
|
|
} = useGraphApi({
|
|
containerTags,
|
|
documentIds,
|
|
limit: maxNodes,
|
|
enabled: containerSize.width > 0 && containerSize.height > 0,
|
|
})
|
|
|
|
return (
|
|
<div ref={containerRef} className="w-full h-full">
|
|
<MemoryGraphBase
|
|
documents={apiData.documents as GraphApiDocument[]}
|
|
apiEdges={apiData.edges as GraphApiEdge[]}
|
|
isLoading={externalIsLoading || apiIsLoading}
|
|
error={externalError || apiError}
|
|
variant={variant}
|
|
maxNodes={maxNodes}
|
|
canvasRef={canvasRef}
|
|
totalCount={apiData.totalCount}
|
|
{...rest}
|
|
>
|
|
{children}
|
|
</MemoryGraphBase>
|
|
</div>
|
|
)
|
|
}
|