/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import { DocSearchButton, useDocSearchKeyboardEvents } from "@docsearch/react" import Head from "@docusaurus/Head" import Link from "@docusaurus/Link" import { useHistory } from "@docusaurus/router" import { translate } from "@docusaurus/Translate" import { useBaseUrlUtils } from "@docusaurus/useBaseUrl" import useDocusaurusContext from "@docusaurus/useDocusaurusContext" import useAlgoliaContextualFacetFilters from "@theme/hooks/useAlgoliaContextualFacetFilters" import useSearchQuery from "@theme/hooks/useSearchQuery" import React, { useCallback, useMemo, useRef, useState } from "react" import { createPortal } from "react-dom" import styles from "./styles.module.css" let DocSearchModal = null const convertToKebabCase = (string) => { return string .replace(/\s+/g, "-") .replace("'", "") .replace(".", "") .replace('"', "") .toLowerCase() } const replaceUrl = (item) => { let { url, hierarchy } = item if (url.includes("api/store") || url.includes("/api/admin")) { url = url.replace("#", "") if (hierarchy.lvl2) { const index = url.lastIndexOf("/") url = url.substring(0, index) + `/${convertToKebabCase(hierarchy.lvl1)}` + url.substring(index) } } return url } function Hit({ hit, children }) { if (hit.url.includes("/api/store") || hit.url.includes("/api/admin")) { const url = replaceUrl(hit) return {children} } return {children} } function ResultsFooter({ state, onClose }) { const { generateSearchPageLink } = useSearchQuery() return ( See all {state.context.nbHits} results ) } function DocSearch({ contextualSearch, ...props }) { const { siteMetadata } = useDocusaurusContext() const contextualSearchFacetFilters = useAlgoliaContextualFacetFilters() const configFacetFilters = props.searchParameters?.facetFilters ?? [] const facetFilters = contextualSearch ? // Merge contextual search filters with config filters [...contextualSearchFacetFilters, ...configFacetFilters] : // ... or use config facetFilters configFacetFilters // we let user override default searchParameters if he wants to const searchParameters = { ...props.searchParameters, facetFilters, } const { withBaseUrl } = useBaseUrlUtils() const history = useHistory() const searchContainer = useRef(null) const searchButtonRef = useRef(null) const [isOpen, setIsOpen] = useState(false) const [initialQuery, setInitialQuery] = useState(null) const importDocSearchModalIfNeeded = useCallback(() => { if (DocSearchModal) { return Promise.resolve() } return Promise.all([ import("@docsearch/react/modal"), import("@docsearch/react/style"), import("./styles.css"), ]).then(([{ DocSearchModal: Modal }]) => { DocSearchModal = Modal }) }, []) const onOpen = useCallback(() => { importDocSearchModalIfNeeded().then(() => { searchContainer.current = document.createElement("div") document.body.insertBefore( searchContainer.current, document.body.firstChild ) setIsOpen(true) }) }, [importDocSearchModalIfNeeded, setIsOpen]) const onClose = useCallback(() => { setIsOpen(false) searchContainer.current.remove() }, [setIsOpen]) const onInput = useCallback( (event) => { importDocSearchModalIfNeeded().then(() => { setIsOpen(true) setInitialQuery(event.key) }) }, [importDocSearchModalIfNeeded, setIsOpen, setInitialQuery] ) const navigator = useRef({ navigate({ item }) { const url = replaceUrl(item) // Need to type out the entire URL to prevent it from attempting to open the page // as part of the docusaurus project. Which will fail. window.location = `https://docs.medusajs.com${url}` }, navigateNewTab({ item }) { const url = replaceUrl(item) const windowReference = window.open(url, "_blank", "noopener") if (windowReference) { windowReference.focus() } }, navigateNewWindow({ item }) { const url = replaceUrl(item) window.open(url, "_blank", "noopener") }, }).current const transformItems = useRef((items) => { return items.map((item) => { // We transform the absolute URL into a relative URL. // Alternatively, we can use `new URL(item.url)` but it's not // supported in IE. const a = document.createElement("a") a.href = item.url return { ...item, url: withBaseUrl(`${a.pathname}${a.hash}`), } }) }).current const resultsFooterComponent = useMemo( () => (footerProps) => , [onClose] ) const transformSearchClient = useCallback( (searchClient) => { searchClient.addAlgoliaAgent("docusaurus", siteMetadata.docusaurusVersion) return searchClient }, [siteMetadata.docusaurusVersion] ) useDocSearchKeyboardEvents({ isOpen, onOpen, onClose, onInput, searchButtonRef, }) const translatedSearchLabel = translate({ id: "theme.SearchBar.label", message: "Search", description: "The ARIA label and placeholder for search button", }) return ( <> {/* This hints the browser that the website will load data from Algolia, and allows it to preconnect to the DocSearch cluster. It makes the first query faster, especially on mobile. */}
{isOpen && createPortal( , searchContainer.current )} ) } function SearchBar() { const { siteConfig } = useDocusaurusContext() return } export default SearchBar