123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- import React, { useRef, useCallback, useState } from "react";
- import classnames from "classnames";
- import { useHistory } from "@docusaurus/router";
- import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
- import { usePluginData } from '@docusaurus/useGlobalData';
- import useIsBrowser from "@docusaurus/useIsBrowser";
- const Search = props => {
- const initialized = useRef(false);
- const searchBarRef = useRef(null);
- const [indexReady, setIndexReady] = useState(false);
- const history = useHistory();
- const { siteConfig = {} } = useDocusaurusContext();
- const isBrowser = useIsBrowser();
- const { baseUrl } = siteConfig;
- const initAlgolia = (searchDocs, searchIndex, DocSearch) => {
- new DocSearch({
- searchDocs,
- searchIndex,
- baseUrl,
- inputSelector: "#search_input_react",
- // Override algolia's default selection event, allowing us to do client-side
- // navigation and avoiding a full page refresh.
- handleSelected: (_input, _event, suggestion) => {
- const url = suggestion.url || "/";
- // Use an anchor tag to parse the absolute url into a relative url
- // Alternatively, we can use new URL(suggestion.url) but its not supported in IE
- const a = document.createElement("a");
- a.href = url;
- // Algolia use closest parent element id #__docusaurus when a h1 page title does not have an id
- // So, we can safely remove it. See https://github.com/facebook/docusaurus/issues/1828 for more details.
- history.push(url);
- }
- });
- };
- const pluginData = usePluginData('docusaurus-lunr-search');
- const getSearchDoc = () =>
- process.env.NODE_ENV === "production"
- ? fetch(`${baseUrl}${pluginData.fileNames.searchDoc}`).then((content) => content.json())
- : Promise.resolve([]);
- const getLunrIndex = () =>
- process.env.NODE_ENV === "production"
- ? fetch(`${baseUrl}${pluginData.fileNames.lunrIndex}`).then((content) => content.json())
- : Promise.resolve([]);
- const loadAlgolia = () => {
- if (!initialized.current) {
- Promise.all([
- getSearchDoc(),
- getLunrIndex(),
- import("./DocSearch"),
- import("./algolia.css")
- ]).then(([searchDocs, searchIndex, { default: DocSearch }]) => {
- if (searchDocs.length === 0) {
- return;
- }
- initAlgolia(searchDocs, searchIndex, DocSearch);
- setIndexReady(true);
- });
- initialized.current = true;
- }
- };
- const toggleSearchIconClick = useCallback(
- e => {
- if (!searchBarRef.current.contains(e.target)) {
- searchBarRef.current.focus();
- }
- props.handleSearchBarToggle && props.handleSearchBarToggle(!props.isSearchBarExpanded);
- },
- [props.isSearchBarExpanded]
- );
- if (isBrowser) {
- loadAlgolia();
- }
- return (
- <div className="navbar__search" key="search-box">
- <span
- aria-label="expand searchbar"
- role="button"
- className={classnames("search-icon", {
- "search-icon-hidden": props.isSearchBarExpanded
- })}
- onClick={toggleSearchIconClick}
- onKeyDown={toggleSearchIconClick}
- tabIndex={0}
- />
- <input
- id="search_input_react"
- type="search"
- placeholder={indexReady ? 'Search' : 'Loading...'}
- aria-label="Search"
- className={classnames(
- "navbar__search-input",
- { "search-bar-expanded": props.isSearchBarExpanded },
- { "search-bar": !props.isSearchBarExpanded }
- )}
- onClick={loadAlgolia}
- onMouseOver={loadAlgolia}
- onFocus={toggleSearchIconClick}
- onBlur={toggleSearchIconClick}
- ref={searchBarRef}
- disabled={!indexReady}
- />
- </div>
- );
- };
- export default Search;
|