json / src /hooks /useFocusNode.ts
xinnni's picture
Upload 146 files
f909d7c verified
raw
history blame
No virus
1.47 kB
import React from "react";
import { useDebouncedValue } from "@mantine/hooks";
import { searchQuery, cleanupHighlight, highlightMatchedNodes } from "src/lib/utils/graph/search";
import useGraph from "src/store/useGraph";
export const useFocusNode = () => {
const viewPort = useGraph(state => state.viewPort);
const [selectedNode, setSelectedNode] = React.useState(0);
const [nodeCount, setNodeCount] = React.useState(0);
const [value, setValue] = React.useState("");
const [debouncedValue] = useDebouncedValue(value, 600);
const skip = () => setSelectedNode(current => (current + 1) % nodeCount);
React.useEffect(() => {
if (!value) {
cleanupHighlight();
setSelectedNode(0);
setNodeCount(0);
return;
}
if (!viewPort || !debouncedValue) return;
const matchedNodes: NodeListOf<Element> = searchQuery(`span[data-key*='${debouncedValue}' i]`);
const matchedNode: Element | null = matchedNodes[selectedNode] || null;
cleanupHighlight();
if (matchedNode && matchedNode.parentElement) {
highlightMatchedNodes(matchedNodes, selectedNode);
setNodeCount(matchedNodes.length);
viewPort?.camera.centerFitElementIntoView(matchedNode.parentElement, {
elementExtraMarginForZoom: 400,
});
} else {
setSelectedNode(0);
setNodeCount(0);
}
}, [selectedNode, debouncedValue, value, viewPort]);
return [value, setValue, skip, nodeCount, selectedNode] as const;
};