Browse Source

add next node feature to search

AykutSarac 3 years ago
parent
commit
665b38b489
2 changed files with 37 additions and 17 deletions
  1. 20 9
      src/components/Input/index.tsx
  2. 17 8
      src/hooks/useFocusNode.tsx

+ 20 - 9
src/components/Input/index.tsx

@@ -13,6 +13,10 @@ const StyledInputWrapper = styled.div`
   padding: 4px 6px;
 `;
 
+const StyledForm = styled.form`
+  display: flex;
+`;
+
 const StyledInput = styled.input`
   background: none;
   color: ${({ theme }) => theme.TEXT_NORMAL};
@@ -48,18 +52,25 @@ const StyledSearchButton = styled.button`
 `;
 
 export const Input: React.FC = () => {
-  const [content, setContent] = useFocusNode();
+  const [content, setContent, skip] = useFocusNode();
+
+  const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
+    e.preventDefault();
+    skip();
+  };
 
   return (
     <StyledInputWrapper>
-      <StyledInput
-        type="text"
-        value={content.value}
-        onChange={(e) =>
-          setContent((val) => ({ ...val, value: e.target.value }))
-        }
-        placeholder="Search Node"
-      />
+      <StyledForm onSubmit={onSubmit}>
+        <StyledInput
+          type="text"
+          value={content.value}
+          onChange={(e) =>
+            setContent((val) => ({ ...val, value: e.target.value }))
+          }
+          placeholder="Search Node"
+        />
+      </StyledForm>
       <StyledSearchButton
         aria-label="search"
         onClick={() => setContent({ value: "", debounced: "" })}

+ 17 - 8
src/hooks/useFocusNode.tsx

@@ -8,6 +8,7 @@ import {
 } from "src/utils/search";
 
 export const useFocusNode = () => {
+  const [selectedNode, setSelectedNode] = React.useState(0);
   const [content, setContent] = React.useState({
     value: "",
     debounced: "",
@@ -17,6 +18,8 @@ export const useFocusNode = () => {
     states: { settings },
   } = useConfig();
 
+  const skip = () => setSelectedNode((current) => current + 1);
+
   React.useEffect(() => {
     const debouncer = setTimeout(() => {
       setContent((val) => ({ ...val, debounced: content.value }));
@@ -32,29 +35,35 @@ export const useFocusNode = () => {
     const matchedNodes: NodeListOf<Element> = searchQuery(
       `span[data-key*='${content.debounced}' i]`
     );
-    const firstMatchedNode: Element | null = matchedNodes[0] || null;
+    const matchedNode: Element | null = matchedNodes[selectedNode] || null;
 
     cleanupHighlight();
 
-    if (zoomPanPinch && firstMatchedNode && firstMatchedNode.parentElement) {
+    if (zoomPanPinch && matchedNode && matchedNode.parentElement) {
       const newScale = 1;
-      const x = Number(firstMatchedNode.getAttribute("data-x"));
-      const y = Number(firstMatchedNode.getAttribute("data-y"));
+      const x = Number(matchedNode.getAttribute("data-x"));
+      const y = Number(matchedNode.getAttribute("data-y"));
 
       const newPositionX =
         (zoomPanPinch.offsetLeft - x) * newScale +
         zoomPanPinch.clientWidth / 2 -
-        firstMatchedNode.getBoundingClientRect().width / 2;
+        matchedNode.getBoundingClientRect().width / 2;
       const newPositionY =
         (zoomPanPinch.offsetLeft - y) * newScale +
         zoomPanPinch.clientHeight / 2 -
-        firstMatchedNode.getBoundingClientRect().height / 2;
+        matchedNode.getBoundingClientRect().height / 2;
 
       highlightMatchedNodes(matchedNodes);
 
       settings.zoomPanPinch?.setTransform(newPositionX, newPositionY, newScale);
+    } else {
+      setSelectedNode(0);
     }
-  }, [content.debounced, settings.zoomPanPinch]);
 
-  return [content, setContent] as const;
+    return () => {
+      if (!content.value) setSelectedNode(0);
+    };
+  }, [content.debounced, settings.zoomPanPinch, selectedNode, setSelectedNode]);
+
+  return [content, setContent, skip] as const;
 };