From a1d202d3b54d7df9728e7394d4e8e1228f149e20 Mon Sep 17 00:00:00 2001 From: arvinxx Date: Sun, 14 Feb 2021 13:58:34 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20feat:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=94=AE=E7=9B=98=E6=8E=A7=E5=88=B6=E4=B8=8A=E4=B8=8B=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../searchBar/app/AnimatedHeight/index.tsx | 27 ----- .../app/SearchResult/AnimatedHeight/index.tsx | 31 +++++ .../searchBar/app/SearchResult/index.tsx | 95 ++++++++-------- .../app/SearchResult/useKeyboardResult.ts | 107 ++++++++++++------ src/contentScripts/searchBar/app/index.tsx | 5 +- 5 files changed, 153 insertions(+), 112 deletions(-) delete mode 100644 src/contentScripts/searchBar/app/AnimatedHeight/index.tsx create mode 100644 src/contentScripts/searchBar/app/SearchResult/AnimatedHeight/index.tsx diff --git a/src/contentScripts/searchBar/app/AnimatedHeight/index.tsx b/src/contentScripts/searchBar/app/AnimatedHeight/index.tsx deleted file mode 100644 index 58c99c7..0000000 --- a/src/contentScripts/searchBar/app/AnimatedHeight/index.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import type { FC } from 'react'; -import React, { useRef } from 'react'; - -import { useSize } from 'ahooks'; -import { useSpring, animated } from 'react-spring'; - -interface AnimatedHeightProps { - maxHeight: number; -} -const AnimatedHeight: FC = ({ children, maxHeight }) => { - const ref = useRef(null); - const { height } = useSize(ref); - - const animaHeightStyle = useSpring({ - height: height || 0, - }); - - return ( - -
- {children} -
-
- ); -}; - -export default AnimatedHeight; diff --git a/src/contentScripts/searchBar/app/SearchResult/AnimatedHeight/index.tsx b/src/contentScripts/searchBar/app/SearchResult/AnimatedHeight/index.tsx new file mode 100644 index 0000000..6ab2616 --- /dev/null +++ b/src/contentScripts/searchBar/app/SearchResult/AnimatedHeight/index.tsx @@ -0,0 +1,31 @@ +import { useSize } from 'ahooks'; +import { useSpring, animated } from 'react-spring'; + +import { forwardRef } from 'react'; + +interface AnimatedHeightProps { + maxHeight: number; +} +const AnimatedHeight = forwardRef( + ({ children, maxHeight }, ref) => { + // @ts-ignore + const { height } = useSize(ref); + + const animaHeightStyle = useSpring({ + height: height || 0, + }); + + return ( + +
+ {children} +
+
+ ); + }, +); + +export default AnimatedHeight; diff --git a/src/contentScripts/searchBar/app/SearchResult/index.tsx b/src/contentScripts/searchBar/app/SearchResult/index.tsx index e0838f5..48dc033 100644 --- a/src/contentScripts/searchBar/app/SearchResult/index.tsx +++ b/src/contentScripts/searchBar/app/SearchResult/index.tsx @@ -6,6 +6,7 @@ import cls from 'classnames'; import { SearchService } from '../useSearchService'; import { useKeyboardResult } from './useKeyboardResult'; import RepoIcon from './RepoIcon'; +import AnimatedHeight from './AnimatedHeight'; import styles from './style.less'; @@ -15,57 +16,61 @@ const SearchResult: FC = () => { resultIndex, handleResultIndex, isFocusOnResult, + resultRef, } = useKeyboardResult(); return ( - - {result?.map((item, index) => { - const { title, info, id, url, target, type } = item; + // @ts-ignore + + + {result?.map((item, index) => { + const { title, info, id, url, target, type } = item; - return ( -
{ - window.open(url); - }} - onMouseEnter={() => { - handleResultIndex(index); - }} - > -
- {type === 'repo' ? ( - { + window.open(url); + }} + onMouseEnter={() => { + handleResultIndex(index); + }} + > +
+ {type === 'repo' ? ( + + ) : ( + + )} +
+
+
- ) : ( - - )} +
{info}
+
-
-
-
{info}
-
-
- ); - })} - + ); + })} + + ); }; diff --git a/src/contentScripts/searchBar/app/SearchResult/useKeyboardResult.ts b/src/contentScripts/searchBar/app/SearchResult/useKeyboardResult.ts index eecc6b1..9e13efa 100644 --- a/src/contentScripts/searchBar/app/SearchResult/useKeyboardResult.ts +++ b/src/contentScripts/searchBar/app/SearchResult/useKeyboardResult.ts @@ -1,4 +1,4 @@ -import { useCallback, useContext, useEffect, useState } from 'react'; +import { useContext, useEffect, useRef, useState } from 'react'; import { SearchService } from '../useSearchService'; import { KeyboardService, handleIndex } from '../useKeyboardService'; @@ -17,9 +17,34 @@ export const useKeyboardResult = () => { } = useContext(KeyboardService); const [resultIndex, setResultIndex] = useState(0); + const resultRef = useRef(null); + console.log('real', resultIndex); + + /** + * 处理结果区高度 + */ + const scrollResultContainer = (index: number, back?: boolean) => { + const { current: ctn } = resultRef; + if (!ctn) return; + + const step = 77; + + if (index === result.length) { + ctn.scrollTop = 0; + } + + if (!back) { + if (index > 3) { + ctn.scrollTop += step; + } + } else if (ctn.scrollTop > 0) { + ctn.scrollTop -= step; + } + }; /** * 按 上下键切换选中的 result + * @param index * @param back */ const switchResultIndex = (back?: boolean) => { @@ -27,55 +52,65 @@ export const useKeyboardResult = () => { setResultIndex(newIndex); }; + const keepResultIndex = () => { + if (resultIndex >= result.length) { + setResultIndex(result.length - 1); + } + }; const handleResultIndex = (index: number) => { focusOnResult(); setResultIndex(index); }; // 将焦点切换到 Options - const onKeyDown = useCallback( - (event: KeyboardEvent) => { - if (focusKey !== 'result') return; - switch (event.key) { - case 'Tab': - event.preventDefault(); - switchOptionIndex(event.shiftKey); - break; - case 'ArrowDown': - event.preventDefault(); - switchResultIndex(); - break; - case 'ArrowUp': - event.preventDefault(); - if (resultIndex === 0) { - focusOnOptions(); - } else { - switchResultIndex(true); - } - break; - case 'ArrowRight': - switchOptionIndex(); - break; - case 'ArrowLeft': - switchOptionIndex(true); - break; - case 'Escape': - focusOnInput(); - break; - default: - } - }, - [focusKey, resultIndex, switchOptionIndex], - ); + const onKeyDown = (event: KeyboardEvent) => { + if (focusKey !== 'result') return; + console.log(resultIndex); + + switch (event.key) { + case 'Tab': + event.preventDefault(); + switchOptionIndex(event.shiftKey); + break; + case 'ArrowDown': + event.preventDefault(); + scrollResultContainer(resultIndex + 1); + switchResultIndex(); + break; + case 'ArrowUp': + event.preventDefault(); + + if (resultIndex === 0) { + focusOnOptions(); + } else { + scrollResultContainer(resultIndex - 1, true); + switchResultIndex(true); + } + break; + case 'ArrowRight': + switchOptionIndex(); + keepResultIndex(); + break; + case 'ArrowLeft': + switchOptionIndex(true); + keepResultIndex(); + break; + case 'Escape': + focusOnInput(); + break; + default: + } + }; useEffect(() => { document.addEventListener('keydown', onKeyDown); return () => { document.removeEventListener('keydown', onKeyDown); }; - }, [onKeyDown]); + }, [focusKey, result, resultIndex, keepResultIndex, switchOptionIndex]); return { + resultRef, resultIndex, handleResultIndex, isFocusOnResult: focusKey === 'result', diff --git a/src/contentScripts/searchBar/app/index.tsx b/src/contentScripts/searchBar/app/index.tsx index 3cf6d2e..93be79e 100644 --- a/src/contentScripts/searchBar/app/index.tsx +++ b/src/contentScripts/searchBar/app/index.tsx @@ -10,7 +10,6 @@ import { KeyboardService, useKeyboardService } from './useKeyboardService'; import SearchInput from './SearchInput'; import SearchResult from './SearchResult'; -import AnimatedHeight from './AnimatedHeight'; import styles from './style.less'; import { isDev } from '@/utils'; @@ -31,9 +30,7 @@ const SearchBar: FC = () => {
- - - +
) : (