import { addClauses, removePhrase, toQueryString, } from 'shared/lib/query/textQueryUtils'; import * as React from 'react'; import { FunctionComponent, useCallback } from 'react'; import { SearchClause, QueryUpdate, } from 'shared/components/query/filteredSearch/SearchClause'; import { QueryParser } from 'shared/lib/query/QueryParser'; import _ from 'lodash'; import { SearchBox } from 'shared/components/query/filteredSearch/SearchBox'; import { StudySearchControls } from 'shared/components/query/filteredSearch/StudySearchControls'; import { observer, useLocalObservable } from 'mobx-react-lite'; import { sleep } from 'shared/lib/TimeUtils'; export type StudySearchProps = { parser: QueryParser; query: SearchClause[]; onSearch: (query: SearchClause[]) => void; }; export const StudySearch: FunctionComponent = observer( function(props) { const store = useLocalObservable(() => ({ isMenuOpen: false, toggle() { this.isMenuOpen = !this.isMenuOpen; }, setMenuOpen(visible: boolean) { this.isMenuOpen = visible; }, })); const onFocusSearchBox = useCallback(() => { store.setMenuOpen(true); }, []); const onBlurSearchBox = useCallback(async () => { // thus pause is necessary to allow clicks // from inside the dropdown menu to update state // before the menu is closed await sleep(200); store.setMenuOpen(false); }, []); const onKeyDownSearchBox = useCallback( (e: React.KeyboardEvent) => { if ([13, 27].includes(e.keyCode)) { store.setMenuOpen(false); } else { store.setMenuOpen(true); } }, [] ); return (
handleQueryTyping(props, update) } onFocus={onFocusSearchBox} onBlur={onBlurSearchBox} onKeyDown={onKeyDownSearchBox} />
0} onClick={() => handleQueryTyping(props, '')} /> { handleQueryUpdate(props, update); store.setMenuOpen(false); }} parser={props.parser} />
); } ); function handleQueryTyping(props: StudySearchProps, update: string) { const updatedQuery = props.parser.parseSearchQuery(update); return props.onSearch(updatedQuery); } function handleQueryUpdate(props: StudySearchProps, update: QueryUpdate) { let updatedQuery = _.cloneDeep(props.query); if (update.toRemove) { for (const p of update.toRemove) { updatedQuery = removePhrase(p, updatedQuery); } } if (update.toAdd) { updatedQuery = addClauses(update.toAdd, updatedQuery); } props.onSearch(updatedQuery); } const SearchMenuToggle: FunctionComponent<{ onClick: () => void; open: boolean; }> = props => { const arrowDirection = props.open ? 'rotate(180deg)' : 'rotate(0deg)'; return (
); }; const ClearSearchButton: FunctionComponent<{ onClick: () => void; show: boolean; }> = props => { return (
x
); };