www/components/fuzzy-bar.tsx

107 lines
3.3 KiB
TypeScript
Raw Normal View History

2021-12-08 03:38:31 +00:00
import { ChangeEvent, useCallback, useEffect, useRef, useState } from 'react';
import Fuzzy from './_fuzzy';
import pages from '../public/pages.json';
import style from '../styles/fuzzy.module.css';
2022-04-27 08:03:21 +00:00
import posts from '../public/posts.json'
2021-12-08 03:38:31 +00:00
function FuzzyBar(): JSX.Element {
const searchField = useRef<any>(null);
const [searchValue, setSearchValue] = useState('');
const [resultsValue, setResultsValue] = useState(<></>);
let [metaKey, setMetaKey] = useState('Ctrl');
const [show, setShow] = useState(false);
let fuzz: Fuzzy | null = null;
let entries = [...pages];
for (const [k,v] of posts.entries()) {
2022-04-24 04:40:26 +00:00
const item = v as any;
if (item.title && item.slug)
entries.push({title: item.title, link: `posts/${item.slug}`});
}
2021-12-08 03:38:31 +00:00
try {
fuzz = new Fuzzy({
pages: entries,
2021-12-08 03:38:31 +00:00
searchField: searchField,
searchValue: searchValue,
resultsValue: resultsValue,
setResultsValue: setResultsValue,
maxResults: 5
});
} catch (e: any) {
console.error(e.message);
}
function searchInput(e: ChangeEvent<HTMLInputElement>) {
setSearchValue(e.target.value);
}
const toggleSearch = useCallback(() => {
setShow(!show);
fuzz?.showSearchResults();
searchField.current?.focus();
}, [fuzz, show]);
useEffect(() => {
if (window.navigator.userAgent.match(/mac[\s]?os/i))
setMetaKey('⌘ Cmd');
}, []);
useEffect(() => {
const event = (e: KeyboardEvent) => {
if (e.code === 'KeyK' && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
2021-12-08 03:38:31 +00:00
toggleSearch();
}
if (e.code === 'KeyP' && (e.ctrlKey || e.metaKey) && e.shiftKey) {
e.preventDefault();
2021-12-08 03:38:31 +00:00
alert('not really sure what to do here lol');
}
if (show)
searchField.current?.focus();
return false;
2021-12-08 03:38:31 +00:00
}
window.addEventListener('keydown', event);
return () => { window.removeEventListener('keydown', event); }
}, [fuzz, show, toggleSearch]);
return (
<>
{
show ?
<div className={`fuzzynav ${style.container}`}>
<input type='text'
className={style.search}
value={searchValue}
placeholder='Go to ...'
ref={searchField}
onChange={searchInput}
onKeyUp={(e) => { fuzz?.searchKeyUpListener(e) }} />
<div
id='results'
className={style.results}>{resultsValue}</div>
</div>
: <></>
}
<a className={style.searchBar} onClick={toggleSearch}>
<span className={style.searchTerm}>Search</span>
<div className={style.keybind}>
<span className={style.key}>{metaKey}</span> <span className={style.key}>K</span>
</div>
</a>
</>
);
}
export default FuzzyBar;