diff --git a/site/comps/Select.tsx b/site/comps/Select.tsx index a8880f5a3..18237db59 100644 --- a/site/comps/Select.tsx +++ b/site/comps/Select.tsx @@ -3,6 +3,7 @@ import View, { ViewProps } from "comps/View" import Text from "comps/Text" import useClickOutside from "hooks/useClickOutside" import useKey from "hooks/useKey" +import { findLastIndex } from "lib/array" interface PromptProps { name: string, @@ -67,7 +68,6 @@ interface SelectProps { } // TODO: scroll to cur at expand -// TODO: jump with key const Select: React.FC = ({ options, value, @@ -78,6 +78,7 @@ const Select: React.FC = ({ const dropdownRef = React.useRef(null) const [ curItem, setCurItem ] = React.useState(value ?? options[0]) + const [ curItemIndex, setCurItemIndex ] = React.useState(0) const [ expanded, setExpanded ] = React.useState(false) useClickOutside(dropdownRef, () => setExpanded(false), [ setExpanded ]) @@ -138,13 +139,42 @@ const Select: React.FC = ({ { - // TODO - console.log(e.key) + const indexFound = options.findIndex((opt, i) => { + if (curItem[0] === e.key) { + if (!curItemIndex) return e.key === opt[0] && i > 0 + if (curItemIndex === findLastIndex(options, curItem, 0)) { + setCurItemIndex(null) + return e.key === opt[0] + } + else return e.key === opt[0] && curItemIndex < i + } else if (curItem[0] !== e.key) { + return e.key === opt[0] + } + }) + + const newItem = options[indexFound] + + if (e.key !== "Enter" && newItem && curItem !== newItem) { + setCurItem(newItem) + setCurItemIndex(indexFound) + + const selected = dropdownRef.current!.children[indexFound] as HTMLDivElement + + if (selected) { + dropdownRef.current!.scrollTop = selected.offsetTop + } + } + + if (e.key === "Enter") { + onChange && onChange(curItem) + } + }} css={{ overflowY: "auto", diff --git a/site/lib/array.ts b/site/lib/array.ts new file mode 100644 index 000000000..90475ff40 --- /dev/null +++ b/site/lib/array.ts @@ -0,0 +1,6 @@ +export const findLastIndex = (array: string[], searchValue: string, searchIndex: number) => { + const index = array.slice().reverse().findIndex((item: string) => item[searchIndex] === searchValue[searchIndex]) + const count = array.length - 1 + const lastIndex = index >= 0 ? count - index : index + return lastIndex +} \ No newline at end of file