import Fuse, { FuseResult } from 'fuse.js' import React, { Fragment, useCallback, useEffect, useState } from 'react' import { Search as SearchIcon } from 'react-feather' import { SearchIndex, SearchItem } from '../utils/search' import { Dialog, Transition, Combobox } from '@headlessui/react' import { useRouter } from 'next/router' export interface SearchProps {} interface SearchResultProps { result: FuseResult selected: boolean active: boolean } const SearchResult: React.FunctionComponent = (props) => { const excerpt = (s: string) => { if (s.length < 120) { return <>{s} } else { return <>{s.substring(0, 120)}… } } const bg_for = (s: string) => { const bg = 'p-1 rounded bg-opacity-20 ' if (s === 'var') { return bg + 'bg-blue-500' } if (s === 'config') { return bg + 'bg-green-500' } if (s === 'lua') { return bg + 'bg-red-500' } return bg } const selection = props.active ? 'bg-slate-300 dark:bg-slate-700' : '' return (
{props.result.item.name}
{props.result.item.kind}

{excerpt(props.result.item.desc)}

) } const Search: React.FunctionComponent = () => { const router = useRouter() const [searchText, setSearchText] = useState('') const [searchResults, setSearchResults] = useState[]>( [] ) const [fuse, setFuse] = React.useState | undefined>( undefined ) const fusePromise = async () => { const data = await fetch('/static/fuse-index.json') console.log(data) const searchIndex: SearchIndex = await data.json() console.log(searchIndex) return new Fuse(searchIndex.list, {}, Fuse.parseIndex(searchIndex.index)) } React.useEffect(() => { fusePromise().then((fuse) => setFuse(fuse)) }, []) const [isOpen, setIsOpen] = useState(false) const handleKeyPress = useCallback( (event: KeyboardEvent) => { if (event.key === 'k' && (event.metaKey || event.ctrlKey) && isOpen) { setIsOpen(false) event.preventDefault() } else if ( (event.key == '/' || (event.key === 'k' && (event.metaKey || event.ctrlKey))) && !isOpen ) { setIsOpen(true) event.preventDefault() } }, [isOpen] ) useEffect(() => { document.addEventListener('keydown', handleKeyPress) return () => { document.removeEventListener('keydown', handleKeyPress) } }, [handleKeyPress]) if (!fuse) { return (
) } const setSearch = (value: string) => { setSearchText(value) const searchResult = fuse.search(value) setSearchResults(searchResult) } const onChange = (value?: FuseResult) => { if (value) { if (value.item.kind === 'var') { router.push(`/variables#${value.item.name}`, undefined, { scroll: false, }) } if (value.item.kind === 'config') { router.push(`/config_settings#${value.item.name}`, undefined, { scroll: false, }) } if (value.item.kind === 'lua') { router.push(`/lua#${value.item.name}`, undefined, { scroll: false }) } setIsOpen(false) } } const closeModal = () => { setIsOpen(false) } const openModal = () => { setIsOpen(true) } return ( <>
setSearch(e.target.value)} />
{searchResults.length === 0 && searchText !== '' ? (
No results.
) : ( searchResults.map((r) => ( {({ selected, active }) => ( )} )) )}
) } export default Search