({
initialQuery: initialQueryProp,
autoFocus = true,
placeholder,
onSubmitQuery,
className,
suggestionType = 'searchPostSuggestions',
onFocus,
onClearQuery,
enableSuggestions = true,
}: PostsSearchProps)
| 57 | } & Pick<HTMLAttributes<HTMLInputElement>, 'onFocus'>; |
| 58 | |
| 59 | export default function PostsSearch({ |
| 60 | initialQuery: initialQueryProp, |
| 61 | autoFocus = true, |
| 62 | placeholder, |
| 63 | onSubmitQuery, |
| 64 | className, |
| 65 | suggestionType = 'searchPostSuggestions', |
| 66 | onFocus, |
| 67 | onClearQuery, |
| 68 | enableSuggestions = true, |
| 69 | }: PostsSearchProps): ReactElement { |
| 70 | const { time, contentCurationFilter, postTypesFilter } = |
| 71 | useSearchContextProvider(); |
| 72 | const { user } = useAuthContext(); |
| 73 | const searchBoxRef = useRef<HTMLDivElement>(null); |
| 74 | const [query, setQuery] = useState<string>(); |
| 75 | const [items, setItems] = useState<string[]>([]); |
| 76 | const { value: searchVersion } = useConditionalFeature({ |
| 77 | feature: feature.searchVersion, |
| 78 | shouldEvaluate: |
| 79 | !!query && |
| 80 | suggestionType === 'searchPostSuggestions' && |
| 81 | enableSuggestions, |
| 82 | }); |
| 83 | const SEARCH_URL = SEARCH_TYPES[suggestionType]; |
| 84 | const purify = useDomPurify(); |
| 85 | const [isFocused, setIsFocused] = useState(false); |
| 86 | const initialQuery = useRef<string>(initialQueryProp || ''); |
| 87 | // `query` only catches up after the suggestion debounce, so submitting has to |
| 88 | // read the raw input value or an early Enter would search for nothing. |
| 89 | const typedQuery = useRef<string>(initialQueryProp || ''); |
| 90 | |
| 91 | const { data: searchResults, isPending } = useQuery<{ |
| 92 | [suggestionType: string]: { hits: { title: string }[] }; |
| 93 | }>({ |
| 94 | // Bookmark and reading-history suggestions are private per user. |
| 95 | queryKey: generateQueryKey(RequestKey.Search, user, suggestionType, query), |
| 96 | queryFn: () => |
| 97 | gqlClient.request(SEARCH_URL, { query, version: searchVersion }), |
| 98 | enabled: !!query && enableSuggestions, |
| 99 | staleTime: StaleTime.Default, |
| 100 | }); |
| 101 | |
| 102 | useEffect(() => { |
| 103 | if (!isPending) { |
| 104 | setItems( |
| 105 | searchResults?.[suggestionType]?.hits.map((hit) => |
| 106 | purify?.sanitize?.(hit.title), |
| 107 | ) ?? [], |
| 108 | ); |
| 109 | } |
| 110 | }, [searchResults, isPending, suggestionType, purify]); |
| 111 | |
| 112 | const submitQuery = async (item?: string) => { |
| 113 | const itemQuery = item?.replace?.(sanitizeSearchTitleMatch, ''); |
| 114 | await onSubmitQuery(itemQuery || typedQuery.current || '', { |
| 115 | filters: { |
| 116 | time: time.toString(), |
nothing calls this directly
no test coverage detected